Notebook C#

Alex van Buitenen

Intro.

This is not a tutorial nor a complete quick reference.
This document is just my personal memo block for C#.

Content.

Retrieve logged on windows username.
Saving User settings.
Application Configuration settings.
Access Configuration information.
Working with Threads.
Sort issues.
Exceptions.
Cursor.
DataGridView.
ComboBox.
Outlook automation.
Word automation.
Walking thru a directory.
Drag and Drop.
Checking whether the user pressed Ctrl/Shift.
Using XmlSerializer to serialize a class to/from XML.
Color FromKnowColor.
CheckedListBox does not give any cues that it is selected.
Handling key press.
Object browser does not display help for my dll.
Defining an icon for a user control to be shown by the Toolbox.
Setting an Approle.
Retrieving Type from string.
Serialize Type to Xml.
AssemblyVersion vs AssemblyFileVersion.
Adding a local report in WinForms.
DateTime.ToString formatting

Retrieve logged on windows username.

using System.Security.Principal;

    WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
    string userName = windowsIdentity.Name;

Saving User settings.

Add a settings file to the project (or rightclick project and choose Settings).
Add a property <PropertyName> to the settings.
Set Scope to User.

Use:
Properties.Settings.Default.<PropertyName>
and
Properties.Settings.Default.Save();

In the Visual Studio 2005 Help, this in not described.
They only explain using My from Visual Basic, and not a C# variant.
See Using Settings in C# in MSDN Online for the missing help.
 

Where are the settings stored?
Somewhere in user.config in
Documents and Settings\<username>\Local Settings\Application Data\
see also Application Settings Architecture in MSDN online.

The settings allow User and Application settings.
Application settings cannot be modified by the user.
Both User and Application settings have their initial values in the app.config file.

Application Configuration settings.

In app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionstrings>
        <add name="PPI" connectionString="Server=(local)\SQLEXPRESS2008;Database=LCT_ONT;Integrated Security=true"/>
    </connectionstrings>
    <appSettings>
        <add key="ServerName" value="rdv10t" />
    </appSettings>
</configuration>

In C# file:

string ServerName = System.Configuration.ConfigurationSettings.AppSettings["ServerName"];
ConnectionStringSettings cs = ConfigurationManager.ConnectionStrings["PPI"];

See MSDN Help, <appsettings>.

Access Configuration information.

To work with configuration files for client applications, use ConfigurationManager (or WebConfigurationManager for ASP).

sample:

ApplicationSettings.Properties.Settings settings = new ApplicationSettings.Properties.Settings();
Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings.Add("Key2", "Value2");
config.Save(); //saves the config file in the in the bin/{Debug|Release} directory

Working with Threads.

definition of MyThreadWithState.CS
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ThreadDemo
{
  // Delegate that defines the signature for the callback method.
  public delegate void MyThreadCallback(int lineCount);

  public class MyThreadWithState
  {
    // State information used in the task.
    private string _message;
    private int _value;

    // Delegate used to execute the callback method when the
    // task is complete.
    private MyThreadCallback callback;

    // The constructor obtains the state information and the
    // callback delegate.
    public MyThreadWithState(string text, int number,
    MyThreadCallback callbackDelegate)
    {
      _message = text;
      _value = number;
      callback = callbackDelegate;
    }

    // The thread procedure performs the task, such as
    // formatting and printing a document, and then invokes
    // the callback delegate with the number of lines printed.
    public void ThreadProc(object param)
    {
      Console.WriteLine("Param = " + param as string);
      for (int i=0;i<3;i++)
      {
        Console.WriteLine("executing ThreadMethod(" + i.ToString() + ")");
        Thread.Sleep(3000);
      }
      Console.WriteLine(_message, _value);
      if (callback != null)
          callback(1);
    }
  }
}
 
usage of MyThreadWithState
private void StartThread()
{
  MyThreadWithState myThreadWithState = new MyThreadWithState(
    "This report displays the number {0}.",
    42,
    new MyThreadCallback(ResultCallback));

  Thread InstanceCaller = new Thread(
  new ParameterizedThreadStart(myThreadWithState.ThreadProc));

  // Start the thread.
  InstanceCaller.Start("Test");
}

// The callback method must match the signature of the callback delegate.
public static void ResultCallback(int lineCount)
{
  Console.WriteLine("Result of callback is: {0}.", lineCount);
}
 

Graphics

Saving Graphics to file.

To be able to save a Graphics object to file, create the Graphics from a BitMap, and then use BitMap.Save to save to file.

private Graphics _graphics;
private Bitmap _bitmap;

_bitmap = new Bitmap(200, 200);
_graphics = Graphics.FromImage(_bitmap);
_bitMap.Save("D:\\temp\\test.bmp");

Scrolling the Graphics

Set Autoscroll to true.

Draw like:
e.Graphics.DrawEllipse(Brushes.Red,10+AutoScrollPosition.X,10+AutoScrollPosition.Y,100,100)

OR

Matrix mx=new Matrix(1, 0, 0, 1, AutoScrollPosition.X, AutoScrollPosition.Y);
e.Graphics.Transform=mx;
e.Graphics.DrawEllipse(Brushes.Red,10,10,100,100)

For explanation about Matrix, see:
GDI+ Graphics in Visual Basic 2005 .NET - Part 5
Matrix Transformation of Images in C#, using .NET GDI+

see also Understanding Windows Forms AutoScroll

Sort issues.

Creating a non-casesensitive sortedList

private SortedList<string,MyType> _constraints = new SortedList<string,MyType>(StringComparer.OrdinalIgnoreCase);

Exceptions.

For guidelines on exceptions, see Catching and Throwing Standard Exception Types on MSDN.

Do not throw System.Exception or System.SystemException.
Do not catch System.Exception or System.SystemException in framework code, unless you intend to re-throw.
Avoid catching System.Exception or System.SystemException, except in top-level exception handlers.

If you are designing an application that needs to create its own exceptions, you are advised to derive custom exceptions from the Exception class.

When creating your own exceptions, it is good coding practice to end the class name of the user-defined exception with the word "Exception."
It is also good practice to implement the three recommended common constructors, as shown in the following example.

using System;
public class EmployeeListNotFoundException: Exception
{
    public EmployeeListNotFoundException() { }
    public EmployeeListNotFoundException(string message) : base(message) { }
    public EmployeeListNotFoundException(string message, Exception inner) : base(message, inner) { }
}

Cursor.

// Memorize the current cursor
Cursor savedCursor = Cursor.Current;
// Set the wait cursor
Cursor.Current = Cursors.WaitCursor;
// Do something time consuming...
//
// Restore the memorized cursor
Cursor.Current = savedCursor;
 

DataGridView.

(re)Setting the current row.

// Get the index of the current row
DataGridViewRow currentRow = dataGridView1.CurrentRow;
int index = dataGridView1.Rows.IndexOf(currentRow);

// Here something happens disturbs the current row of the DataGridView, like a refresh of  the contents of the DataGridView.
//...

// Now restore the previously selected row
if (index > 0)
{
    if (index < dataGridView1.Count)
        {
            DataGridViewRow selectedRow = dataGridView1.Rows[index];
            dataGridViewPotentielePublicatiegroepen.CurrentCell = selectedRow.Cells[0];
        }
}
 

Cannot insert row in databound DataGridView.

Problem:
DataGridView does not contain a line with "*" that indicates you can add a new row.

Cause:

List<ParameterInfo> coll = new List<ParameterInfo>()
//dataGridView1.DataSource = coll;
//Oeps, forgot that Visual Studio has added a BindingsSource as a level of indirection:
//this.dataGridView1.DataSource = this.parameterInfoBindingSource;
//So setting the DataSource should be done in the BindingSource:
parameterInfoBindingSource.DataSource = coll;

Empty row in DataGridView even though Datasource has 0 records.

Solved by setting checking DataSource's Count, and setting Datasource to null if neccessary.

Get Selected record in DataGridView

Want to use a DataGridView to select one line. (Set MultiSelect of the DataGridView to False)
Replace DATABOUNDITEM by the type of the databound item.

/// <summary>
/// Gets the DATABOUNDITEMRecord which is selected in the DataGridView.
/// </summary>
/// <returns>the selected DATABOUNDITEM record.</returns>
/// <remarks>
/// Picks the selected row, otherwise the row of the selected cell.
/// Assuming the DataGridView only allows single selection.
/// </remarks>
private DATABOUNDITEM GetDATABOUNDITEMRecord()
{
    DataGridViewRow dataGridViewRow = null;
    DATABOUNDITEM myItem = null;
    if (dataGridViewDATABOUNDITEM.SelectedRows.Count > 0)
    {
        // Get selected row using SelectedRows.
        dataGridViewRow = dataGridViewDATABOUNDITEM.SelectedRows[0];
        if (dataGridViewRow != null)
        {
            myItem = dataGridViewRow.DataBoundItem as DATABOUNDITEM;
        }
    }
    else
    {
        // Get selected row using SelectedCells
        int rowIndex;
        if (dataGridViewDATABOUNDITEM.SelectedCells.Count > 0)
        {
            rowIndex = dataGridViewDATABOUNDITEM.SelectedCells[0].RowIndex;
            dataGridViewRow = dataGridViewDATABOUNDITEM.Rows[rowIndex];
            if (dataGridViewRow != null)
            {
                myItem = dataGridViewRow.DataBoundItem as Correspondentie;
            }
        }
    }
    return myItem ;
}

ComboBox.

Checklist on ComboBox

Error while setting SelectedIndex on Databound ComboBox, Value of '0' is not valid for 'SelectedIndex'.

Got error using this code:

// Put operator in a ComboBox
// Define the operators

const string GT = ">";
const string GTE = ">=";
const string EQ = "=";
const string LTE = "<=";
const string LT = "<";

// Put them in an array
string[] _operatorItems = new string[5] { GT,GTE,EQ,LTE,LT };
// Create the Combobox
ComboBox comboBox = new ComboBox();
// Only allow items from the List
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
// Databind it
comboBox.DataSource = _operatorItems;
comboBox.SelectedIndex = 0;

InvalidArgument=Value of '0' is not valid for 'SelectedIndex'.
Parameter name: SelectedIndex

Tried setting SelectedItem, SelectedValue.
Doesn't work.

Cause:

Items is not filled (because Databinding was used)

Solution:

//Don't use Databinding, just fill Items:
foreach (string str in _operatorItems)
{
  comboBox.Items.Add(str);
}

Outlook automation.

Voeg een reference toe : Microsoft.Office.Interop.Outlook
(Voor VS2010 is dit: C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Outlook.dll )
MSDN Help: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.aspx

How to: Obtain and Log On to an Instance of Outlook
C# Outlook 2007 COM interop application does not exit!
Microsoft .NET Development for Microsoft Office (Part 2).
See example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using System.Reflection;
using System.Threading;
using System.Runtime.InteropServices; 
//Uit C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Outlook.dll
using Outlook = Microsoft.Office.Interop.Outlook;

namespace TestOutlook
{
    public class OutlookWorker
    {
        public bool SendEmail(
            string subject, string body, string to, string from,string fromName, string [] attachments)
        {
            bool ok = false;
            bool startedNewOutlook = false;

            //The MAPI profile name, as a String (string in C#), to use for the session. 
            //Specify an empty string to use the default profile for the current session.
            string mapiProfile = "";

            try
            {
                Outlook.Application oApp = null;
                Outlook.NameSpace ns = null;
                // Check if there is an Outlook process running. 
                if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
                {

                    // If so, use the GetActiveObject method to obtain the process and cast it to an Application object. 
                    oApp = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
                }
                else
                {
                    // If not, create a new instance of Outlook and log on to the default profile.
                    oApp = new Outlook.Application();

                    ns = oApp.GetNamespace("MAPI");
                    ns.Logon(mapiProfile, "", Missing.Value, Missing.Value);
                    
                    startedNewOutlook = true;
                }
                Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);

                oMsg.HTMLBody = body;

                int iPosition = (int)oMsg.HTMLBody.Length + 1;
                int iAttachType = (int)Outlook.OlAttachmentType.olByValue;

                if (attachments != null)
                {
                    foreach (string attachment in attachments)
                    {
                        String sDisplayName = Path.GetFileName(attachment);
                        Outlook.Attachment oAttach =
                            oMsg.Attachments.Add(
                                attachment,
                                iAttachType,
                                iPosition,  //This parameter applies only to e-mail messages using 
                            //Microsoft Outlook Rich Text format: 
                            //it is the position where the attachment should be placed 
                            //within the body text of the message. 
                            //A value of 1 for the Position parameter specifies that 
                            //the attachment should be positioned at the beginning of 
                            //the message body. A value 'n' greater than the number 
                            //of characters in the body of the e-mail item specifies 
                            //that the attachment should be placed at the end. 
                            //A value of 0 makes the attachment hidden.
                                sDisplayName);
                    }
                }
                oMsg.Subject = subject;
                Outlook.Recipients oRecips = (Outlook.Recipients)oMsg.Recipients;
                Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add(to);

                oRecip.Resolve();
                oMsg.Send();

                ok = true;
                if (startedNewOutlook)
                {
                    ns.Logoff();
                    ns = null;
                    ((Outlook._Application)oApp).Quit();
                }

                // See MSDN, Microsoft .NET Development for Microsoft Office (Part 2)
                // http://msdn.microsoft.com/en-us/library/aa679807%28office.11%29.aspx#officeinteroperabilitych2_part2_rco
                //
                //In the previous code we reference the Outlook.Application object and the Outlook.MailItem object. 
                //Both are COM objects that are implicitly created when we use the property. 
                //We don't keep any managed references to these objects ourselves, 
                //but that in itself confuses many developers. 
                //The CLR will have wrapped these objects for us, and because we don't have explicit 
                //references to them, we have no way of explicitly releasing them. 
                //Instead, we rely on the CLR to release them on our behalf.
                //
                //(If you look at the task manager, OUTLOOK.EXE only stops after the calling program has ended.)
                //There are a couple of ways of making our cleanup operations more deterministic—and more aggressive.


                //method 1: Simple Garbage Collection
                //perform simple cleanup, by nulling the references and forcing garbage collection:
                oRecip = null;
                oRecips = null;
                oMsg = null;
                oApp = null;

                GC.Collect();
                GC.WaitForPendingFinalizers(); 
                //it takes a moment, but OUTLOOK.EXE stops (when a new instance was started).
                
                //method2: Marshal.ReleaseComObject
                //As an alternative, you can use Marshal.ReleaseComObject. 
                //However, note that you are very unlikely to ever need to use this method. 
                // (So we don't do that here, but leave the comment for documentation purposes)
                //
                //Marshal.ReleaseComObject(oMsg);
                //while (Marshal.ReleaseComObject(oApp) > 0) {}

            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                MessageBox.Show(ex.Message, "Error while sending mail", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (System.IO.FileNotFoundException ex)
            {
                MessageBox.Show(ex.Message, "Error while sending mail", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (System.UnauthorizedAccessException ex)
            {
                MessageBox.Show(ex.Message, "Error while sending mail", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return ok;
        }
    }
}

Word automation.

Voeg een reference toe : Microsoft.Office.Interop.Word
(Voor VS2010 is dit: C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Word.dll)
MSDN Help: Word primary interop assembly reference.

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Threading;

// Uit C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Word.dll
using Word = Microsoft.Office.Interop.Word; 

namespace TestWord
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// See http://msdn.microsoft.com/en-us/library/ms228772.aspx
    /// and http://social.msdn.microsoft.com/Forums/en-CA/vsto/thread/1dab0874-bba5-481a-9986-a11a66efa0a0
    /// </remarks>
    public class WordTemplateWorker
    {
        private Word.Application _wordApplication = null;
        private Word.Document _wordDocument = null;

        /// <summary>
        /// -Accepts a Word template (with extension .dotx) as parameter
        /// -fills in the template fields.
        /// -Saves the filled template as .docx file.
        /// </summary>
        /// <param name="templateName"></param>
        /// <returns></returns>
        public bool ProcessTemplate(
            string templateName,
            string destinationFilename,
            Dictionary<string,string> keyValues)
        {
            bool success = false;

            //Start Word
            _wordApplication = new Word.Application();
            if (_wordApplication != null)
            {
                _wordApplication.Visible = false;

                //Add template to document
                success = AddingTemplateToDocument(templateName);
                if (!success)
                    MessageBox.Show("AddingTemplateToDocument failed");

                //fill template
                if (success)
                    success = FillingTemplate(keyValues);

                if (!success)
                    MessageBox.Show("FillingTemplate failed");

                //save filled template
                if (success)
                {
                    // save as docx.
                    _wordDocument.SaveAs2(destinationFilename as object, Word.WdSaveFormat.wdFormatDocumentDefault);
                }

                if (_wordDocument != null)
                    (_wordDocument as Word._Document).Close();

                (_wordApplication as Word._Application).Quit();

            }
            return success;
        }


        private bool AddingTemplateToDocument(string templateName)
        {
            bool success = false;
            int retryCounter = 0;
            do
            {
                try
                {
                    retryCounter++;
                    _wordDocument = _wordApplication.Documents.Add(templateName as object);
                    //this worked fine in the debugger with breakpoints, but wordDocument was null without the breakpoints.
                    // keep trying for a while. 
                    // See also: remarks of this class.
                    if (_wordDocument != null)
                        success = true;
                }
                catch (System.Runtime.InteropServices.COMException ex)
                {
                }
            } 
            while ((success == false) && (retryCounter < 10));

            return success;
        }

        private bool FillingTemplate(Dictionary<string,string> keyValues)
        {
            int retryCounter = 0;
            bool success = false;
            do
            {
                try
                {
                    retryCounter++;
                    Console.WriteLine("retryCounter = " + retryCounter.ToString());
                    FillTemplate(keyValues);
                    success = true;
                }
                catch (System.Runtime.InteropServices.COMException ex)
                {
                    Thread.Sleep(1000); // Didn't work properly, give Word some time to initialize.
                    //if ((UInt32)ex.ErrorCode == 0x80010001)
                    //    MessageBox.Show("ErrorCode0x80010001");
                    //MessageBox.Show(ex.Message + " "+ ex.ErrorCode.ToString());
                }
            } while ((success == false) && (retryCounter < 10));

            return success;
        }

        private void FillTemplate(Dictionary<string,string> keyValues)
        {
            //De aanroep van _wordDocument.Fields kan een COMException opleveren.
            // "Aanroep geweigerd door aangeroepene. (Uitzondering van HRESULT: 0x80010001
            // RPC_E_CALL_REJECTED))"
            foreach (Word.Field wordField in _wordDocument.Fields)
            {
                if (wordField.Type == Word.WdFieldType.wdFieldMergeField)
                {
                    Word.Range range = wordField.Code;
                    string fieldname = GetFieldnameFromRange(range).ToUpper();
                    if (keyValues.ContainsKey(fieldname))
                    {
                        string fieldValue = keyValues[fieldname];
                        if (fieldValue != null)
                            VulField(wordField, _wordApplication, fieldValue);
                    }
                }
            }

        }

        private void VulField(
            Word.Field wordField,
            Word.Application wordApplication,
            object value)
        {
            wordField.Select();
            wordApplication.Selection.TypeText(value.ToString());
        }

        private string GetFieldnameFromRange(Word.Range range)
        {
            // range heeft onderstaand formaat
            //  MERGEFIELD voornaam \* MERGEFORMAT
            string[] strArray = range.Text.Trim().Split(' ');
            return strArray[2];
        }

        public bool Print(string fileName)
        {
            bool ret = false;
            Word.Application wordApplication = null;
            Word.Document wordDocument = null;
            try
            {
                wordApplication = new Word.Application();
                wordDocument = new Word.Document();
                wordApplication.Visible = false;
                object documentName = fileName;
                wordDocument = wordApplication.Documents.Add(documentName);

                wordDocument.PrintOut();
                ret = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Het printen van het Word document " + fileName + "is mislukt\n\r" +
                    (ex.InnerException == null ? ex.Message : ex.InnerException.Message),
                    "Fout tijdens het printen.",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);

            }
            finally
            {
                if (wordDocument != null)
                    (wordDocument as Word.Document).Close();
                if (wordApplication != null)
                    (wordApplication as Word.Application).Quit();
            }
            return ret;
        }
    }
}


Walking thru a directory.

using System.IO;

DirectoryInfo directoryInfo = new DirectoryInfo(templateLokatie);
IEnumerable<FileInfo> ifileInfos = directoryInfo.EnumerateFiles("*.dotx");

//Create a List because ListBox doesn't accept a IEnumerable
List<FileInfo> fileInfos = new List<FileInfo>();
foreach (FileInfo fi in ifileInfos)
{
    fileInfos.Add(fi);
}


Drag and Drop.

For extensive examples.see MSDN

  1. Start DoDragDrop from within MouseDown or ItemDrag.
    from MSDN: "Certain controls have custom drag-specific events. The ListView and TreeView controls, for example, have an ItemDrag event."

    private void treeView_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
    {
        DoDragDrop(e.Item , DragDropEffects.Copy | DragDropEffects.Move);
    }
    OR
    private void listBoxFields_MouseDown(object sender, MouseEventArgs e)
    {
        DoDragDrop(listBoxFields.SelectedItem, DragDropEffects.Link);
    }

     
  2. Set the AllowDrop property of the control you want to drop on to True.
  3. In the DragEnter, set e.Effect to the desired DragDropEffect.

    private void treeView1_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.Text))
            e.Effect = DragDropEffects.Copy;
        else
            e.Effect = DragDropEffects.None;

        // Make sure the treeview gets the focus, otherwise the nodes
        // don't give any feedback when they are selected in DragOver.
        treeView1.Focus();
    }
  4. In the DragDrop event for the control where the drop will occur, use the GetData method to retrieve the data being dragged.

    TreeNode treeNode = e.Data.GetData(typeof(TreeNode_FinObjects)) as TreeNode;
    OR
    string str = e.Data.GetData(typeof(string)) as string;

Checking whether the user pressed Ctrl/Shift.

 private void MyControl_KeyDown(object sender, KeyEventArgs e)
{
    _shiftPressed = e.Shift;
    _ctrlPressed = e.Control;
}

Using XmlSerializer to serialize a class to/from XML.

using System.Xml;
using System.Xml.Serialization;

[XmlInclude(typeof(MyClass2))] //<- Use XmlInclude to include types not known at compile time (MyClass2 not included in this sample)
class MyClass
{
    private string _name;
    private string _sample;

    public static MyClass ReadFromXml(string fileName)
    {
        StreamReader streamReader = new StreamReader(fileName);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyClass));
        object obj = xmlSerializer.Deserialize(streamReader);
        MyClass myClass = obj as MyClass;
        return myclass;
    }

    public void WriteToXml(string fileName)
    {
        XmlWriterSettings ws = new XmlWriterSettings();
        ws.NewLineHandling = NewLineHandling.Entitize;
        ws.Indent = true;

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyClass));
        using (XmlWriter xmlWriter = XmlWriter.Create(fileName, ws))
        {
        xmlSerializer.Serialize(xmlWriter, this);
        }
    }

[XmlAttribute] //<- use XmlAttribute to write as attribute, instead of node
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    [XmlIgnore] //<- use XmlIgnore to prevent writing to xml.
    public string Sample
    {
        get { return _sample; }
        set { _sample = value; }
    }
}

Color FromKnowColor.

Controls have a Color such as "Window" for BackColor in the properties window of Visual Studio.
However, BackColor is a Color, ans class Color doen not have "Window".
There is a class "KnownColor" that has "Window", but you cannot cast from KnowColor to Color.

Use Color.FromKnownColor(KnownColor.Window);
 

CheckedListBox does not give any cues that it is selected.

// Focus the CheckedListBox on the right side
// (Set input focus to the control.)
// The control can have the input focus while not displaying any visual cues of having the focus.
 
checkedListBox_UDFs.Focus();
// Indeed, it does not give any visual cues
// Select the control.
// (Activates a control.)
checkedListBox_UDFs.Select();
//Still no visual cues

Solved by giving background color when Entering/leaving the control:

 private void checkedListBox_UDFs_Enter(object sender, EventArgs e)
{
    checkedListBox_UDFs.BackColor = Color.FromKnownColor(KnownColor.ControlLight);
}

private void checkedListBox_UDFs_Leave(object sender, EventArgs e)
{
    checkedListBox_UDFs.BackColor = Color.FromKnownColor(KnownColor.Window);
}

Handling key press.

event key info parameter
KeyDown KeyEventArgs
KeyPress KeyPressEventArgs
KeyUp KeyEventArgs

KeyEventArgs has more info than KeyPressEventArgs. If you want to handle arrow keys, use KeyDown/KeyUp instead of KeyPress!

Object browser does not display help for my dll.

Make sure the XML documentation file (that can be generated by Visual Studio; Project properties, Build, Xml Documentation file)
is placed next to the Dll you want to browse with object browser.

Defining an icon for a user control to be shown by the Toolbox.

Create a bitmap (in my case 16x16, 16 color)
Set Build action to embedded resource.
Set "Copy to output directory"to "Copy if newer"
Use the ToolboxBitmap attribute:
[ToolboxBitmap("TextBoxOpenFile.bmp")]
public class TextBoxOpenFile : System.Windows.Forms.UserControl

Setting an AppRole

In app.config:

<add key="AppRoleName" value="AppRolename" />
<add key="AppRolePassword" value="EncryptedPassword" />

Na het connecten met de database SetApprole uitvoeren:

 private void SetAppRole()
{
  string appRoleName = ConfigurationManager.AppSettings["AppRoleName"];
  string appRolePassword = ConfigurationManager.AppSettings["AppRolePassword"];
  appRolePassword = Encryption.Decrypt(appRolePassword);

  // Activate AppRole
  SqlCommand activateAppRole = new SqlCommand();
  activateAppRole.CommandText = "sp_setapprole";
  activateAppRole.CommandType = CommandType.StoredProcedure;
  activateAppRole.Connection = _conn;
  activateAppRole.Parameters.AddWithValue("@rolename", appRoleName);
  activateAppRole.Parameters.AddWithValue("@password", appRolePassword);
  int success = activateAppRole.ExecuteNonQuery();
  if (success != -1) 
    {
      throw new Exception("Activating approle '" + appRoleName + "' has failed");
    }
}

Retrieving Type from string.

Type type =  Type.GetType("System.Int32");

Serialize Type to Xml

/// <summary> 
/// Type as string to serialize
/// </summary>
 [XmlAttribute("Type")]
public string TypeString
{
  get {  return _type.ToString(); }
  set {  _type = Type.GetType(value); }
}
/// <summary> 
/// Type
/// </summary>
[XmlIgnore]
public Type Type
{
  get { return _type; }
  set { _type = value; }
}

AssemblyVersion vs AssemblyFileVersion.

see AssemblyInfo.cs

AssemblyVersion attribute.

The version number has four parts, as follows:
<major version>.<minor version>.<build number>.<revision>

You can specify all the values or you can accept the default build number, revision number, or both by using an asterisk (*).
If you specify an asterisk for the build number, you cannot specify a revision number.

default build number increments daily. The default revision number is random.

AssemblyFileVersion attribute.

The file version is normally a string of four numbers, separated by periods, reflecting the major version number, minor version number, build number, and revision number; for example, "1.0.4309.00". If version is not in this format, a compiler warning occurs, and the results displayed in the file properties dialog are unpredictable. Wildcards are not supported.

Source: MSDN

If you are a .NET developer, Assembly and File version would be familiar to you. They can be set in the Designer UI (project Properties page, Application tab, Assembly Information button...) which basically updates appropriate attributes in AssemblyInfo.cs.

Now, there is a less well known number - the Product version. It is not well documented and most developers ignore it altogether with no side-effects most of the time. However, it is an important number and it seems that, of the three, Product version is the most widely used.

The three version numbers simply take the values you give them or:

a. If Assembly version is not explictly specified, it takes the value of 0.0.0.0.
b. If File version is not explicitly specified, it takes the value of Assembly version.
c. If Product version is not explicitly specified, it takes the value of File version.

In Windows Explorer of Windows XP and Server 2003, you can see from the properties of a file all three version numbers. In Windows Vista and later, you can't see Assembly version anymore.

To see the assembly version of a file in Vista or later without writing a program, simply type the following in Windows PowerShell: [Reflection.AssemblyName]::GetAssemblyName('xxxx.dll').Version.
Where xxxx.dll is the full path of your assembly

Source: http://all-things-pure.blogspot.nl/2009/09/assembly-version-file-version-product.html

 

DateTime.ToString formatting

sample: dateTime.ToString("yyyyMMdd")

Custom Date and Time Format Strings