Archive for September, 2010

Binding a Windows Forms ComboBox in C#


Most often when reading the selected item of a bound combobox you will need more information than just the selected text or the selected index of the combo. For example, if you have a combobox bound to a user table in your database, you will most probably want to have the full user name displayed in the combobox, but when a user is selected you will want to work with the user code or user id. In this case the combo’s selected index is of no use and neither is the display text. You need a way to be able to retrieve the user code when a user is selected.

Fortunately, this is quite easy to accomplish. All we need to do is bind our combobox to a list of KeyValuePair objects. In this article I am going to show you how to do exactly that.

To start off create a form which looks similar to the below one:

Now in the Form_Load event handler we must add the following code:

private void MainForm_Load(object sender, EventArgs e)
{
    // Create a List to store our KeyValuePairs
    List> data = new List>();

    // Add data to the List
    data.Add(new KeyValuePair("p1", "Joe"));
    data.Add(new KeyValuePair("p2", "David"));
    data.Add(new KeyValuePair("p3", "Keith"));
    data.Add(new KeyValuePair("p4", "Andrew"));
    data.Add(new KeyValuePair("p5", "Maria"));

    // Clear the combobox
    cboData.DataSource = null;
    cboData.Items.Clear();

    // Bind the combobox
    cboData.DataSource = new BindingSource(data, null);
    cboData.DisplayMember = "Value";
    cboData.ValueMember = "Key";
}

In the first line of code we are creating a List object to store our KeyValuePair objects. The KeyValuePair class can be very useful since it allows you to create a pair of objects of any type, one of which is the key and the other is the value. What this means is that you can have an object of type string paired with a key of type integer for example. Or you could have a value of type MyClass with a key of type string. The combinations are limitless.

As you can see in the code, we are creating a KeyValuePair where both the key and the value are strings. We are then adding data to the List object by creating KeyValuePair instances and adding them to our List. Next we are clearing the combobox as a precaution (just in case it was populated with something already), and finally we are binding the combobox to the List.

The last two lines of the above code are critical for your binding to work correctly. We must tell the combo which is the DisplayMember and which is the ValueMember of our KeyValuePair so that it will know which object from the pair to display and which to use as the key.

Once you have created the above code run your project and you will see that the combobox is populated with the above names. The key value however cannot be seen, so let’s create some code to visually see the selected key.

Subscribe to the SelectedIndexChanged event of your combobox and add the following code:

private void cboData_SelectedIndexChanged(object sender, EventArgs e)
{
    // Get the selected item in the combobox
    KeyValuePair selectedPair = (KeyValuePair)cboData.SelectedItem;

    // Show selected information on screen
    lblSelectedKey.Text = selectedPair.Key;
    lblSelectedValue.Text = selectedPair.Value;
}

What we are doing here is retrieving the combo’s selected item and converting it to a KeyValuePair object. Then from our KeyValuePair object we are accessing the Key and the Value properties and assigning them to the labels on our form.

Now if you run the application again you should have something like the following, and as you can see the key and value are being displayed in our labels.

Now using this technique you can easily bind a combobox and have one value displayed while another value is used as your key.

Advertisements

Create a Worker Thread for your Windows Form in C#


When performing a relatively heavy operation on your Windows Form, what often happens is that your application’s UI will freeze until the heavy operation completes. This is usually unacceptable because your application’s end user will think it crashed and probably try to close it. To solve this problem you need to run your heavy operation on a separate thread from that of your UI. This way you will be able to run your operation while also keep the end user informed of the progress from the UI. In this article I will show you how to do just that.

First let’s create a form with a textbox which displays the progress of the heavy operation, and two buttons, one to start the process and one to stop it.

Next we need to create our heavy operation method. For this example let’s just create a loop which iterates for 1 million times.

private void HeavyOperation()
{
    // Example heavy operation
    for (int i = 0; i <= 999999; i++)
    {
    }
}

Now let’s declare our thread and a boolean flag used to stop the heavy operation. We must use the System.Threading namespace to access the Thread class.

// Declare our worker thread
private Thread workerThread = null;

// Boolean flag used to stop the
private bool stopProcess = false;

Next in the start button event handler method, we will initialise the thread and tell it to run the HeavyOperation method.

private void btnStart_Click(object sender, EventArgs e)
{
    this.stopProcess = false;

    // Initialise and start worker thread
    this.workerThread = new Thread(new ThreadStart(this.HeavyOperation));
    this.workerThread.Start();
}

Your code should be able to compile and run but you won’t see anything happening because we still have to display the heavy operation’s progress on the UI.

This is where Delegates come in. In .NET a delegate is a form of type-safe function pointer. From the HeavyOperation method which is being run under the worker thread, we cannot access the UI thread directly because it would cause a cross-thread operation exception. This is because the UI thread and our worker thread are running independently of each other and cannot access objects which have not been created by themselves.

So to write to our status textbox which is on the UI from our worker thread, we must use a delegate. At the top of our class declare a delegate and an instance of the delegate as shown below:

// Declare a delegate used to communicate with the UI thread
private delegate void UpdateStatusDelegate();
private UpdateStatusDelegate updateStatusDelegate = null;

Next initialise the delegate in form load for example:

private void Form1_Load(object sender, EventArgs e)
{
    // Initialise the delegate
    this.updateStatusDelegate = new UpdateStatusDelegate(this.UpdateStatus);
}

As you can see in the above code, the delegate is being passed the method name UpdateStatus. This method will be used to display activity indication to the end user. Now let’s create the method:

private void UpdateStatus()
{
    this.txtProgress.Text += "*";
}

Next, let’s update our HeavyOperation method to call the delegate, which updates the status:

private void HeavyOperation()
{
    // Example heavy operation
    for (int i = 0; i <= 999999; i++)
    {
        // Check if Stop button was clicked
        if (!this.stopProcess)
        {
            // Show progress
            this.Invoke(this.updateStatusDelegate);
        }
        else
        {
            // Stop heavy operation
            this.workerThread.Abort();
        }
    }
}

As you can see, to call the delegate we are using the Invoke keyword, which executes the delegate on the UI thread, since we are calling Invoke from the this object.

And to add the final touch to our application, we must add an event handler for the stop button and set the stopProcess flag to true.

private void btnStop_Click(object sender, EventArgs e)
{
    this.stopProcess = true;
}

Now if you run the application and click on your start button, you will see the status textbox filling up with the “*” character. What’s happening is your worker thread is iterating for 1 million times and for each iteration a star is written to the textbox using the delegate.

How to Capture System Events using C#


What are system events? Well, basically they are events raised by the operating system when a user performs an action which affects the operating environment.

System events are accessible through the Microsoft.Win32.SystemEvents class.

SystemEvents Events
Below is a list of all the system events found within the SystemEvents class.

Name Description
DisplaySettingsChanged Occurs when the user changes the display settings.
DisplaySettingsChanging Occurs when the display settings are changing.
EventsThreadShutdown Occurs before the thread that listens for system events is terminated.
InstalledFontsChanged Occurs when the user adds fonts to or removes fonts from the system.
LowMemory Obsolete. Occurs when the system is running out of available RAM.
PaletteChanged Occurs when the user switches to an application that uses a different palette.
PowerModeChanged Occurs when the user suspends or resumes the system.
SessionEnded Occurs when the user is logging off or shutting down the system.
SessionEnding Occurs when the user is trying to log off or shut down the system.
SessionSwitch Occurs when the currently logged-in user has changed.
TimeChanged Occurs when the user changes the time on the system clock.
TimerElapsed Occurs when a windows timer interval has expired.
UserPreferenceChanged Occurs when a user preference has changed.
UserPreferenceChanging Occurs when a user preference is changing.

Note: Some of these system events may not be raised on Windows Vista.

Example Application
As an example let’s create a simple Windows Forms Application and place two buttons and a textbox on the main form. The buttons are going to subscribe and unsubscribe from the system events and the textbox is going to display the captured event details.

In our application we are going to listen for the following four system events: InstalledFontsChanged, DisplaySettingsChanged, TimeChanged, and UserPreferenceChanged. The code for this is shown below:

private bool eventHandlersCreated;

private void btnStartListening_Click(object sender, EventArgs e)
{
    this.StartListening();
}

private void btnStopListening_Click(object sender, EventArgs e)
{
    this.StopListening();
}

private void StartListening()
{
    Microsoft.Win32.SystemEvents.InstalledFontsChanged += new EventHandler(FontHandler);
    Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(ScreenHandler);
    Microsoft.Win32.SystemEvents.TimeChanged += new EventHandler(TimeHandler);
    Microsoft.Win32.SystemEvents.UserPreferenceChanged += new Microsoft.Win32.UserPreferenceChangedEventHandler(PreferenceChangedHandler);

    this.eventHandlersCreated = true;
}

private void StopListening()
{
    Microsoft.Win32.SystemEvents.InstalledFontsChanged -= new EventHandler(FontHandler);
    Microsoft.Win32.SystemEvents.DisplaySettingsChanged -= new EventHandler(ScreenHandler);
    Microsoft.Win32.SystemEvents.TimeChanged -= new EventHandler(TimeHandler);
    Microsoft.Win32.SystemEvents.UserPreferenceChanged -= new Microsoft.Win32.UserPreferenceChangedEventHandler(PreferenceChangedHandler);

    this.eventHandlersCreated = false;
}

As you can see in the StartListening and StopListening methods we are subscribing and unsibscribing to the system events. Each event handler delegate is calling a particular method, and these methods are shown below:

private void FontHandler(object sender, EventArgs e)
{
    txtStatus.Text += string.Format("Installed fonts changed. {0}", Environment.NewLine);
}

private void PreferenceChangedHandler(object sender, Microsoft.Win32.UserPreferenceChangedEventArgs e)
{
    txtStatus.Text += string.Format("You changed a setting: {0} {1}", e.Category.ToString(), Environment.NewLine);
}

private void ScreenHandler(object sender, EventArgs e)
{
    txtStatus.Text += string.Format("Screen resolution changed. {0}", Environment.NewLine);
}

private void TimeHandler(object sender, EventArgs e)
{
    txtStatus.Text += string.Format("System time changed. {0}", Environment.NewLine);
}

If you were to run this application and then go and change the screen resolution for example, the DisplaySettingsChanged event will fire and its delegate will call our ScreenHandler method, and you will see the text Screen resolution changed in the textbox.

Below is a screenshot of our application:

Note: Since these system events are static events, you must make sure you detach your event handlers when disposing your application, or you will end up with memory leaks!

To take care of this memory leak potential problem, when closing our application we are calling the StopListening method to unsubscribe from the event handlers.

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.eventHandlersCreated)
        this.StopListening();
}

Note: Do not perform time-consuming processing on the same thread that raises a system event handler because it might prevent other applications from functioning.

If your application must perform time-consuming processes, do the processing on a separate worker thread and not on the same thread which raises the system events.

Create and Read Cookies in ASP.NET


Cookies are small pieces of text which are created by websites and stored by the Internet browser in its cache for later use. Typically a cookie would contain information related to a surfer’s session in a particular website, such as the user name, items in a shopping cart, page layout preferences, etc.

When a surfer visits a website, a cookie would be created with his details, and when he returns to the site his details are loaded from the cookie and sent to the website. This can for example, allow the website to identify who the surfer is and load his last session back.

Cookies can be very useful but they are also easily accessible so it’s advisable to never store sensitive data, such as passwords or credit card numbers, in cookies.

In this short article I am going to show you how to create a cookie in ASP.NET, obviously using C#, and then I will also show you how to read your cookie’s value.

First you must create an ASP.NET Web Application, and once that’s done add two buttons and a label to your Default.aspx web form. The first button we will call“Save Cookie” and the second one “Load Cookie”. The label will be used to display the status on-screen.

In the event handler for the “Save Cookie” button we will create a cookie and add astring value to it. The code should look like this:

protected void btnSave_Click(object sender, EventArgs e)
{
    // Create a cookie object
    HttpCookie cookie = new HttpCookie("TestCookie");

    // Set the cookie's value
    cookie.Value = "Paul Mercieca";

    // Set the cookie's expiration date
    cookie.Expires = DateTime.Now.AddDays(7);

    // Add the cookie to the cookie collection
    Response.Cookies.Add(cookie);

    // Display the status
    lblStatus.Text = "Cookie has been created.";
}

The above code is quite simple. We are creating a cookie called “TestCookie” and assigning it my name as a value. Then we are setting an expiry date of 7 days for the cookie. This means that the cookie will remain valid for 7 days from creation. When that period expires the cookie will be deleted by the web browser. Finally we are adding our new cookie to the Response.Cookies collection which is actually an instance of HttpCookieCollection, and we are setting the status label’s text.

Now to read the cookie. To do this we need to access the HttpCookieCollection instance again by calling Request.Cookies as can be seen in the below code:

protected void btnLoad_Click(object sender, EventArgs e)
{
    // Retrieve the cookie from the cookie collection
    HttpCookie cookie = Request.Cookies["TestCookie"];

    // Verify the cookie exists
    if (cookie != null)
    {
        lblStatus.Text = string.Format("Hello {0}", cookie.Value.ToString());
    }
    else
    {
        lblStatus.Text = "Cookie not found.";
    }
}

Again, this code is very straight forward. All we are doing here is retrieving the “TestCookie” and verifying it exists. If it exists we are displaying the cookie’s value, which in this case is my name – “David Azzopardi”, and if it does not exist we are displaying “Cookie not found”.

And there you have it – creating and reading cookies with C# in ASP.NET.