Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Sunday, June 22, 2014

Coding Practice: Displaying Bitmaps from Pixel Data

I'm not sure what you do when you wake up early and can't get back to sleep. For some reason, I decided to read about machine learning, and I ended up somewhere I didn't expect.

I went from this:


To building an application that does this:


Along the way, I watched the trial-and-error approach I took to solve a problem. So, here it is with the mistakes (and still not quite good code) and the working solution.

You can download the completed code here: http://www.jeremybytes.com/downloads.aspx#CPDB.

[Update: 7/11/2015: Project has been uploaded to GitHub: https://github.com/jeremybytes/digit-display]

[Update 06/27/2016: This project has been expanded beyond what's shown in this article. To see the code here, check the "DigitDisplay" branch on GitHub: jeremybytes/digit-display Branch DigitDisplay.]

How I Got There
So, I started by running a search for articles on machine learning with F#. And I came across lots of links from my friend Mathias Brandewinder (http://www.clear-lines.com/blog/). I guess I'll really have to attend one of his machine learning workshops the next time we're both in the same place.

After bouncing through a few links, I ended up looking at a Kaggle competition (https://www.kaggle.com/c/digit-recognizer/data). The challenge is to build a system that can recognize hand-written digits. Now, I knew that I was not up to that challenge (complex algorithms are something I need to work up to). But I looked at the sample data files, and I got a bit intrigued.

The sample data was in .csv format. And it was basically a comma-separated collection of values between 0 and 255 that represented the darkness of a pixel. The data sets were there to help you train and test your system. But I thought it might be interesting to try to display the images in an application.

Here's what a record looks like:

1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,188,255,94,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,191,250,253,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123,248,253,167,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,247,253,208,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,207,253,235,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,54,209,253,253,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,254,253,238,170,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,210,254,253,159,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,209,253,254,240,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,253,253,254,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,206,254,254,198,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,253,253,196,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,203,253,248,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,188,253,245,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,253,253,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,240,253,195,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,220,253,253,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,253,253,253,94,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,251,253,250,131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,214,218,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

For the training data, the first value (1 in this case) is the number represented by the data. Then there are 784 values that represent a 28 by 28 pixel bitmap. And there were lots of records in the file.

Step 1: Build a Parser
I created my WPF shell application, and then created a library to handle loading the file and parsing the strings into integer arrays and turning the arrays into bitmaps.

I knew I could parse the file pretty easily; I've done that lots of times before. But I wasn't quite as sure about turning a big string of characters into a bitmap. So, that's where I started.

Here was my first shot at it:


I started by splitting the CSV string into an array. But this is an array of strings; I needed integers. So, I looped through the strings and parsed them into integers. Note that I don't have any error handling here. If there is bad data, this whole thing will blow up. But the dataset I was working with was "clean", so I didn't worry about it. Then I took the flat integer array and parsed it into a 28x28 array.

But I wasn't at all sure that I got this right. In fact, I'm famous for being "off by one". Since I knew that I was still a long way off from creating a bitmap, I figured it would be best to create some unit tests to at least make sure that I'm parsing the array correctly.

This was a bit tedious because I had to take my sample input (just part of it here):


And turn it into 28 arrays of 28 elements each (what my expected output was):


This was a lot of counting, copying, and pasting. But I eventually got the data set up.

After that, the tests were pretty easy (there are 2 other tests that have the other "chunks" of arrays):


And what I found is that I was off by one. In the code that sets the "pixelIndex", I was subtracting one (to account for the first value that I wanted to discard). Instead, I should have been adding one. Here's the corrected code:


Since I knew that my 28 x 28 array was correct, I moved on to creating the bitmap image. As a side note, my unit testing pretty much stopped here. The rest of the code deals with images -- and even better, I had no idea what these images were supposed to look like (as we'll see). So, I didn't have much that I could test.

Step 2: Creating the Bitmap
I now had an integer array that I could work with: int[28,28]. This represented the pixels that I needed to create the bitmap. Here was my first stab at that:


I'm not a big fan of nested "for" statements. But I was just trying to get the job done here. I used this to copy the values from the arrays into the pixels from the bitmap image. Since these are grayscale, I applied the value to the RGB values. So if the value was 238, I would get an RGB value of "238, 238, 238".

I really didn't know if this code was right or not. I needed to display this somehow to find out. But first, I had to load the data.

Step 3: Parse the File
I created another class that would load the data from the CSV file. I just created a static method that would parse the file and generate an array of strings (that I could then pass to the methods I already created).


This checks the config file for the file name, and then looks for the file in the same folder as the executable. Then it just loops through the file and creates an array of strings where each string represents a separate bitmap/digit.

There's a note that we're skipping the first line. That's because the training file (the one I'm using here) has a header row that enumerates the columns.

Now it was time to start putting things together.

Step 4: Displaying a Bitmap
I flipped over to my WPF application, added an <Image> element to the markup, and then flipped to the code behind to populate that image.

I was doing pretty good for a while...


But now what? There's no way to directly assign as System.Drawing.Bitmap (the type that I had) to a WPF Image control.

Fortunately, the developer's friend, StackOverflow, had my solution: http://stackoverflow.com/a/6775114. So, I created a static class for this code and completed the method.


Now it was time for the moment of truth -- running the application:


At least I got an image. But it doesn't look quite right. Time to read the instructions (from the Kaggle site):
Each image is 28 pixels in height and 28 pixels in width, for a total of 784 pixels in total. Each pixel has a single pixel-value associated with it, indicating the lightness or darkness of that pixel, with higher numbers meaning darker. This pixel-value is an integer between 0 and 255, inclusive.
Okay, so I got my light/dark reversed. In my image, the higher numbers represent lighter values. Let's fix the method by subtracting the value from 255 (to invert it):


And see how that looks:


Much better. And I know from looking at the data, that this should be a number "1".

Step 5: Displaying All the Digits
So, I successfully parsed and displayed a single digit image. Next it was time to try to display a lot of them. I swapped out my <Image> for a <ListBox> and then created the image items to put into the list in code:


This just get the first 10 items, loops through them, and generates bitmaps. Then it creates WPF Image controls for each one and puts it into the ListBox. Here's the output:


Not quite what I wanted. It needs some size constraints:


I set the height and width to 28 since that matched the pixel dimensions. The output was much better:


So, I increased to 100 items:


Then 1000:


And this is where I start to look at the data. Something's not right.

Step 6: Fixing the Image
These numbers don't look quite right. It almost looks like some of them are upside down and some of them are backwards. I thought at first that this might have been intentional. But after staring at it for a bit more, I knew things weren't right on my end.

This probably had something to do with the X-Y coordinate system. Some systems use the top left corner as 0,0. Some systems use the bottom left corner as 0,0. Instead of trying to change my arrays, I figured it would be easier to manipulate the bitmap after it's created. So, I played around a bit with the "RotateFlip" method until I found a setting that worked:


That seems to take care of things:


Much better.

Step 7: Final Image Fix
There was one last thing that bothered me. The digits looked blurry. It made sense that they would be blurry when they were stretched out (like in the initial display), but they should be at the native sizes now.

Or should they?

That's when I remembered how WPF worked. When you set the height and width of controls, you don't actually set pixel sizes; you set device-independent units. This is so that WPF can scale appropriately on different DPI devices. As a side note, I really appreciate the scaling now that I'm using a high-resolution display.

Instead of setting the height and width to "28", let's set them to the size of the image itself:


This gives us more digits per line (they are a bit smaller). But none of them are blurry now.


You can click on the image to see the full-resolution version.

Step 8: Functional Style
Since I started out this experiment looking for functional programming ideas, I figured it would be good to incorporate a few in the application.

I made "GenerateDigitArray" and "GetBitmapFromDigitArray" into static methods. And the "LoadDataStrings" was already static.



What's important about these methods is that they are atomic -- they do not depend on any external state or the state of the class that they are in. They do not make any modifications to existing objects. They take parameters and return separate objects. That means they can operate completely independently and have no side effects.

By making them static, they also become easier to use in our code:


This code shows that we do not need to create instances of the FileLoader or the DigitBitmap objects. We just use the static methods that are on those classes.

We can definitely take this further, and the functions are fairly specific by only dealing with 28x28 arrays. But this is a really good place to start. And again, one of the important things is that we consciously think about these functional concepts.

Step 9: General Clean-Up
That's the working application that I wanted. I know, it's not a very exciting application. But it's kind of cool to think that I'm displaying all of these hand-written numbers based only on comma-separate values.

I did a little bit of clean-up after this. I won't go into all the details (you can check the code download if you're interested). I made a change to the "LoadDataStrings" method. In my main code, I wanted to get rid of the "for" loop in the main block of code and make it a "foreach" so I could process however many records were in the file. You can see this by looking at the previous code sample.

[Update: 7/11/2015: Project has been uploaded to GitHub: https://github.com/jeremybytes/digit-display]

[Update 06/27/2016: This project has been expanded beyond what's shown in this article. To see the code here, check the "DigitDisplay" branch on GitHub: jeremybytes/digit-display Branch DigitDisplay.]

The problem is the first time I did this, my computer just started spinning. That's when I checked the file and found that there were over 40,000 items. That's a bit much to process into images all at once. So, I added a "threshold" parameter to the "LoadDataStrings" method. That way I could say, "Just give me the first 1,000 values". And it would be easier to experiment with. It needs a bit of optimization to work with that many records, and the WPF ListBox may not be the best choice of controls for displaying that many items. It's something to think about further.

Wrap Up
You never know where coding explorations will take you. I found this to be a good exercise for me -- a way to do a few things that I've never done before. And hopefully you've gotten a bit of insight by seeing my thought process. I don't always get things right the first time. And that's perfectly okay. But by working in small steps, it's really easy to keep making progress.

Happy Coding!

Sunday, July 7, 2013

Changing Culture in WPF

I know my blog has been a bit empty over the last 6 weeks or so.  I've been working heavily on my C# Interfaces course for Pluralsight which released last week.  So now it's time to catch up on some articles that I've been intending to write.

This time around, we'll look at a bit of a hack that makes changing the culture in a running WPF application a bit easier than the majority of the solutions out there.  The sample project can be downloaded here: http://www.jeremybytes.com/Downloads.aspx#WPFCC.

Using the Machine Culture is Easy
.NET provides us a fairly straightforward way to support different languages and cultures in our applications. By default, our applications use the culture for the machine that they run on.  This means that if we provide resource files with different strings (or images or whatever) that are appropriate for a language, we get the behavior basically for free.

For example, we can provide a resource string in a resx file:


We have resource files set up for "en-US", "en-GB", and "en-AU":


Then in our XAML code, we just need to reference that resource string rather than providing a hard-coded string:


Notice that our "Text" property of this TextBlock references the static "Greeting" string resource.  So, when our application runs, it will automatically get the culture-specific value.

Here's the output:


And we can see "Howdy, Y'all!" is used in our TextBlock.  If our machine is set to a different culture, then we would get that culture-specific string (or the default culture if it's not available).

Note: This isn't a tutorial on how to localize your application, so you'll need to dig into that yourself.  We're just getting the basics in place so we can look at the "hack".

[Update Jan 2014: If you do want to learn how to localize an application in .NET, you can check out my Introduction to Localization and Globalization in .NET course available on Pluralsight.]

Changing the Culture is Hard
So, we've seen how easy it is to use the machine culture.  And, in fact, it's not hard to put in a custom culture (different from the machine) as the application is starting up.  But if we want to change the culture while the application is running, we run into a bit of a problem.

The "free" behavior that we get above (culture-specific resource strings from a file) only happens when the WPF window is being created.  This means that even if we change the culture of our thread while our application is running, the open windows will continue to use the already-bound resource strings -- no automatic updates.

The Scenario
The first question you might ask is "Why do we want to change culture in a running app?"  Well, I ran across this issue while helping a friend working on a project.  He was building a kiosk application in WPF that needed to support multiple languages.  The idea is that the user would walk up to the kiosk, press the button for the language they wanted, and then go from there.

If you cruise the internet, you will come across some interesting solutions.  Some people have built libraries where you call a method to rebind all of the resources of an open window.  I'm not a big fan of this solution just because it seems overly complicated.  And some of the libraries required you to put an attached property on all of the UI controls.

The most basic recommendation to change the culture of your application is to shut down and restart the app.  The idea behind this is that you update a configuration file with the new culture that you want.  Then you restart the application (which is never as easy as it sounds).  When the app starts up, it uses the new culture from configuration.

The "restart" solution sounded like the better solution of these two, but then I had a kind of crazy idea.

The Application MainWindow Property
In my sample code for my session on Dependency Injection (Dependency Injection: A Practical Introduction), I manually create the MainWindow for a WPF application.

Here's what the simplified code looks like (from App.xaml.cs):


The Application.Current.MainWindow is a property on our application that tells us what the main window is.  When the main window is closed, the application itself shuts down.  In this example, we create a new instance of the MainWindow class (which is defined by MainWindow.xaml) and then assign it to the MainWindow property of the application.  Then we Show the MainWindow.

The effect of this is that the MainWindow class is shown.  And when it is closed, the application shuts down.

So, I started to wonder if we could hack around with the MainWindow property a little bit so that we could simply create a new window (with a different culture) rather than shutting down the entire application.

The Hack: Resetting the Main Window
In the App.xaml.cs file, I added a new static method that would swap out the main window of the application.  Here's the code:


Let's step through this.

First, we set the CurrentCulture and the CurrentUICulture for the current thread.  The CurrentCulture defines the culture that the thread operates on.  The CurrentUICulture determines which resource file is going to be used.  For example, if we set the CurrentUICulture to a CultureInfo for "en-US", it will use the resources that are defined in the "Resources.en-US.resx" file (which gets translated into its own assembly/folder when the app is compiled).

We want to set the CurrentUICulture *before* we create the window.  This makes sure that the correct resources will be picked up.

After setting the culture, we create a local variable ("oldWindow") that points to the currently assigned MainWindow. We grab a reference so that we can programmatically close this window later.

Then we create a new MainWindow instance (again, this is coming from MainWindow.xaml).  This will be created with the resources for the new culture.  We assign it to the MainWindow property, and it becomes the main window for the application.

Next, we show the (new) MainWindow.

As a last step, we close the "old" window -- the one with the previous culture.  Since this is no longer the application's "MainWindow", it does not shut down the application.

The result is that the application will have a noticeable "window opening / window closing" effect, but we've managed to do this without shutting down the application.

The Results
Let's see the result in our sample application.  First, as we've seen, we have a TextBlock that uses the "Greeting" resource string.  In addition to that, we have 3 other text blocks.  In the code, we show the current culture, and we assign a date to display with both the short date format and the long date format.

Here's the code for that:


"displayDate.ToString("d")" gives us the short date format, which is "MM/dd/yyyy" in en-US.  "displayDate.ToString("D")" gives us the long date format, which is "dddd, MMMM dd, yyyy" in en-US.

We also have 3 buttons to change the culture.  Each button is similar.  Here's the click handler for the "US" button:


We can see that this calls the ChangeCulture method we looked at earlier.  This will re-create the window.  The constructor of the MainWindow calls "UpdateUIElements" to put the appropriate values in the text blocks.

Here are the outputs if we click each button in turn:




We can see that the "Greeting" text is different for each window.  Also, the short date and long date formats are appropriate to the culture.

As a bit of a humorous side note: I originally used today's date for the sample.  But since today is July 7, 2013, it would be very difficult to tell the difference between "07/07/2013" and "07/07/2013".

Wrap Up
So, this is a bit of a hack to re-create the main window for a WPF application.  But it is easier than restarting the application with new configuration values.  And with the kiosk scenario, it isn't a problem if we "reset" the entire application when the language is changed.

You might be able to use this same hack in a Windows Forms application (although getting to the application is a little less straight-forward).  It may also work in Silverlight by resetting the RootVisual (but I have not tried that).  I seriously doubt that it would work in a Windows 8 App Store app; this is also based on speculation since I have not done much with those types of apps.

Sometimes we come up with creative solutions to specific problems.  This one probably isn't very widely applicable, but it's fun to see what we can come up with nonetheless.

Happy Coding!

Sunday, March 3, 2013

Application Guidance Update: Kona and Prism

Back in December, I mentioned that there were updates coming for application guidance on WPF/Silverlight (Prism) and for Windows Store Apps (Kona).  Well, here's a few more interesting things to look at.

Kona: Guidance for Building Windows Store LOB Apps
The biggest news is that the Kona guidance for building Windows Store Apps is moving forward.  Brian Noyes was on .NET Rocks last week (http://www.dotnetrocks.com/default.aspx?showNum=847) talking about the work that Microsoft Patterns & Practices is putting into their latest guidance package.  If you're interested in carrying over a Prism-like development style to Windows Store Apps, then this episode is definitely worth the listen.

Kona isn't released quite yet; it's still in beta.  But Brian mentioned that they are doing (near) weekly drops on the Codeplex pages; check out the latest here: http://konaguidance.codeplex.com/.  At the time of this writing, the latest version is from February 22, 2013.  It looks like the release will happen sometime in March, but keep your eyes on the site.

Why Not Prism for Windows Store Apps?
One question that came up during the .NET Rocks episode is why Kona is a separate guidance package rather than an extension of the current Prism framework.  There are a couple of primary reasons.

First, Windows Store Apps are different enough from WPF and Silverlight apps that the approaches to development may not translate well.  So, rather than trying to fit a square peg into a round hole, the team decided to start from scratch.  The approach was to first build a Line of Business application (the type that a corporate developer might build) and then work backwards to see what common items can be made easier by extracting them into the Kona framework.

Next, there are certain things in Prism that just don't make sense in the Windows Store App world.  For example, Prism includes extensive support for Regions -- a way to put different views into different parts of the shell.  In the full-screen world of Windows Store Apps (it's killing me not to just say "Metro" here...), the idea of regions just doesn't fit.

Additionally, Prism has good support for dynamically loading modules.  This gives you the ability to drop assemblies into a folder that can then get loaded into the application at runtime.  In the Windows Store App world, all of the assemblies need to be included in the package that is submitted to the store.  So, there's no way to just "drop in a new assembly".  All of the functionality needs to be included up front.

So, it makes sense that the Kona guidance is separate from Prism.  I haven't taken a close look at Kona yet (I still haven't jumped into the Windows Store App world), so I don't have any opinions at this point.  But, if I do need to build line of business applications for Windows Store Apps, I'll definitely start here.

Prism 4.5
One other interesting thing that Brian mentioned is that Prism is basically "done".  That doesn't mean that it has hit end-of-life or anything like that (so don't panic).  It just means that the framework has gone as far as it needs to, so we shouldn't expect new features at this point.

Prism has been compiled to work against the .NET 4.5 framework (you can get the latest from Codeplex: http://compositewpf.codeplex.com/releases/view/95815).  But the features and functionality are the same as Prism 4.1.  Brian did mention that we can expect an updated version when Patterns & Practices releases the next version of Unity, but there won't be any new functionality.

Wrap Up
I'm not necessarily an advocate of using either Prism or Kona.  As with any framework, you need to take a close look at the problems that the framework addresses.  If you don't have those problems, then it's probably not the right framework for you.

As mentioned previously (Five Months In: Working with Prism and WPF), Prism worked very well on the last major project I was involved with.  But we also had many of the concerns that the framework set out to solve (such as Regions, Navigation, Modularity, and MVVM helpers).  Your mileage may vary.

It's always good to know what's available.  Then we are more likely to pick the right tool for the job when it's time to build a particular type of application.  Keep expanding the toolbox.

Happy Coding!

Sunday, July 22, 2012

First Impressions: Working with Prism in WPF

Three weeks ago, I started working with Prism on a WPF application.  Here are a few of my first thoughts:

The Good
Prism is an extremely powerful framework.  It provides classes to help you manage all parts of your WPF application (or Silverlight or Windows Phone 7 -- I'm sure that Metro will be coming soon).  So far, I've worked with the following features:
  • Modules / Module Catalog
  • UI Composition  / Regions / Region Manager
  • Navigation
  • Dependency Injection
  • Event Aggregation
  • Other "Helper" Objects
The Bad
Prism is not for beginning programmers.  If you do not have a solid grasp on intermediate .NET topics, then much of the Prism framework is going to look like magic incantations.  This can only lead to misuse of the framework classes, and most likely this misuse will lead to not getting the benefits (such as good separation of concerns, re-use, and testability).

Before using Prism, you should have a good foundation with the following topics:
  • Dependency Injection / Inversion of Control
  • Interfaces
  • Delegates / Func<T> / Action<T>
  • Lambda Expressions
  • Events and Event Handlers
  • Model-View-ViewModel (MVVM)
  • Various other Design Patterns
As a side note, the documentation ("A Developer's Guide to Microsoft Prism 4" -- available as a PDF or as a tree-book) has an appendix dedicated to the primary design patterns used by Prism.  This includes Adapter, Application Controller Pattern, Command Pattern, Composite and Composite View, Dependency Injection Pattern, Event Aggregator Pattern, Facade Pattern, Inversion of Control Pattern, Observer Pattern, Presentation Model Pattern, Registry Pattern, Repository Pattern, Separated Interface and Plug-In, and Service Locator Pattern.

Good Collection of Features
Prism is an extremely powerful framework and has gone through several iterations and refinements.  The current version (4.1) even includes support for Silverlight 5.  The Patterns & Practices team has obviously put a lot of work into the framework, and my experience so far has been bug-free (from the framework perspective at least -- I'm working on making my own code bug-free).  Let's take a closer look at the features that I've experienced so far:

Modules / Module Catalog
Modules allow you to separate your application functionality into discrete units that can be "plugged in" to the application.  The modules can (should?) be designed to be application agnostic and self-contained.  This means that they can be re-used in other applications.  For example, if you have a need for Customer Maintenance, this could be its own module.  If you have proper separation of concerns, then this module could be used in multiple applications.

For the application I am working on, we have modularized most of the application "screens".  These are being tied together through a work flow.  As a (fictional) example, to take a customer order over the phone, you could start with the Customer module (either entering new customer data or selecting an existing customer), moving on to a Shopping Cart module (where products and quantities are selected), then to a Shipping module, then to a Payment module.  If these modules are designed to work in isolation, then they can be reused in the same application in different work flows.

The Module Catalog keeps track of all of the modules in the application.  This can be set explicitly by specifying types and assemblies, or it can be done much more dynamically.  In our project, the bootstrapper process (that loads the module catalog) searches all of the assemblies in a particular folder and catalogs / initializes any modules that it finds in there.

UI Composition / Regions / Region Manager
The Region Manager is another very powerful tool.  It lets you associate different Views with different Regions of the UI.  This allows you to bring several Views together into a single "screen" for the user.  Different Views can interact with each other (through the Event Aggregator) and still remain programmatically isolated.  The idea is very similar to how a Master Page in an ASP.NET application allows you to have multiple web forms shown in different areas of a single "page".

Navigation
The Navigation infrastructure adds quite a bit of functionality to moving between views.  For example, what do you do if you have unsaved data in a View and the user wants to navigate to another View?  WPF does not have anything built in for this scenario, but Prism does.

Prism offers the IConfirmNavigationRequest interface that can be added to your Views or ViewModels (as a side note, many of the Prism features can be added to either the View or the ViewModel and they behave the same -- this gives you great flexibility depending on whether you are coding View-first or ViewModel-first in your application).  This interface has a ConfirmNavigationRequest method.

When using the Navigation infrastructure, you call "RequestNavigate" (notice the word "request").  The method parameters include a callback that runs when the navigation completes successfully.  But, when RequestNavigate is called, ConfirmNavigationRequest is fired on the View/ViewModel that you are navigating from.  This gives that View/ViewModel the chance to confirm or cancel the navigation.  For example, if the current View/ViewModel has unsaved data, it can prompt the user to Save, Discard Changes, or Cancel.  Cancel would then cancel the navigation, and the current View would remain in place.  Otherwise, the "from" View/ViewModel can simply call the callback, and navigation completes normally.

There are also other methods in the interface (part of INavigationAware and IConfirmNavigationRequest) that allow you to run code "OnNavigatedFrom" (to clean up any resources in the current View/ViewModel) or "OnNavigatedTo" (to initialize the new View/ViewModel).

This functionality is very powerful, and if you did not use what comes with Prism, you would probably end up building a lot of this yourself.  I speak from experience: I implemented a much simpler ICloseQueryable interface on a simple form manager used in a non-Prism application (for more information, see XAML App Review - Part 2: Form Manager).

Dependency Injection
You won't be able to use Prism effectively without dependency injection.  In order to have good separation of concerns for the modularity, MVVM presentation pattern, and other cross-cutting concerns, Prism needs a dependency injection container.  Prism ships with implementations for using Unity (from Patterns & Practices) and MEF (built into .NET 4.0), but you can build your own implementations for using a different DI container (or just cruise the web; I'm sure other people have created implementations for the most popular DI containers).

I've been working with Unity on our project.  With Unity, you can use both Constructor Injection (where the dependencies are specified as parameters in the constructor) and Property Injection (where public properties are flagged as "Dependency" and automatically resolved).

Dependency Injection lets your Views/ViewModels get access to the cross-cutting classes in your application.  For example, you could have an Authorization or Logging service/class that gets injected into each View/ViewModel.  This way, if the Module is used in a different application, the ViewModels will automatically get the cross-cutting services that are registered for that application.

In a Prism application you will (hopefully) make heavy use of interfaces.  For example, the ViewModel could have a dependency on a Model interface, and this dependency could be injected with constructor injection.  This gives you the flexibility of swapping out the Model when you want to unit test the ViewModel.

In this scenario, the application would use the DI container to associate the IModel with the concrete Model (with "RegisterType" if you're using Unity).  If this registration is done at the Module level, then the dependency can be correctly injected everywhere it is used. In the unit tests, you could create a mock of IModel that is registered with the test container.  This makes it very easy to unit test your ViewModel without having to worry about a specific implementation of that Model (such as one that needs a network connection to a service).

I'll be talking more about Unit Testing with Prism and Unity in a future article.  That's an interesting topic in and of itself.

Event Aggregation
With all the loose-coupling that is going on in Prism, it could be very difficult to communicate between modules.  This is where the EventAggregator comes in.  The EventAggregator allows one module to Publish an event (with a particular payload), and any other module can Subscribe to that event.  The two modules do not need to know directly about one another.  One is simply publishing an event, and the other is simply listening for an event.  Neither cares about where the event is coming from nor where it's going.

The EventAggregator takes things another step beyond the normal eventing model in .NET.  The Subscribe method also gives you the opportunity put in a condition based on the payload.  For example, you could say that you want to Subscribe to a StockUpdateEvent, but only if the payload has a StockTickerID of "GM".  The event is published normally, but your event handler only fires if the payload has that particular value in it.

Other "Helper" Objects
Prism also provides helper objects that are designed to make life easier (often by reducing boiler-plate code).  Two of my favorites are NotificationObject and DelegateCommand.

The NotificationObject (Prism) is a base class that implements INotifyPropertyChanged (.NET).  Pretty much all of your ViewModels and/or Models will need to implement INotifyPropertyChanged in order for the data binding to behave as expected.  NotifcationObject is a concrete class that implements INotifyPropertyChanged, so you don't need to include the boiler-plate code for that interface in every single object.

DelegateCommand (Prism) simplifies commanding and the implementation of ICommand (.NET).  Commanding is a much larger topic, but the usual process is to create a class that implements the ICommand interface (this can be a class embedded in the class that uses it or a completely separate class).  ICommand has 2 primary methods: Execute (which is the command code) and CanExecute (which determines whether the command can be run -- this can enable/disable a button tied to the command based on a particular state).

DelegateCommand replaces this separate class with a constructor that takes 1 or 2 delegates as parameters. The first delegate is the code for the command to run ("Execute") and the second delegate is for the "CanExecute" (if you don't provide this, it will always be "true").  Again, this class helps to cut down the boiler-plate code of creating an ICommand object and eliminates the need for a separate type.  Since it is part of your class, the delegates also have access to the internal members/state of the containing class.

Putting It All Together
These features all come together with the goal of making the application easier to maintain, more testable, and reusable.

One main thing to note: you don't have to use all of these features.  If you decide that you do not want to use the Region Manager or Navigation, that's fine.  If you don't want to use the Event Aggregator, that's fine, too.  You can use just the features that you want.  Also Prism does not assume that you are using the MVVM pattern; you don't need to use MVVM, but Prism provides helpers to make the pattern easier to implement.  And even though the features are mostly optional, I think that you'll find yourself using most of these features for any non-trivial application.

I've read about Prism (and previously about the Composite Application Guidance for WPF) and have found it interesting.  At the time, I was concerned about a lot of the apparent magic that is going on (and I am still concerned about this).  It is imperative that you have a good handle on the foundational principles used in Prism before you get started.  If you have a good foundation, then you can build very solid (yet de-coupled, maintainable, testable, and modular) applications.

Three weeks is not that long to have worked with a framework such as Prism.  I'm amazed at how much more I know about Prism than I did prior to this project; much of this is due to a couple of folks on the team who have used Prism successfully in prior projects.  There's still some learning to do on the finer points, and we are still tweaking our implementations a bit, but the larger functionality has fallen into place.

[Update: Here are some thoughts after working with Prism for a while: Five Months In: Working with Prism in WPF]

Happy Coding!

Tuesday, March 13, 2012

XAML Tip: Gradients

XAML makes a lot of things easier. Technically, everything you can do in XAML can also be done in other UI platforms, but XAML just makes it so simple that you're more likely to do them.  What this also means is that we need to think a bit differently when it comes to designing our UIs.

Gradients in the Real World
First, I'll start by saying that I am not a designer; most of these tips have come people way smarter than I am.  Personally, I like gradients -- probably a little bit too much.  They have the ability to make some things look more natural.

There are no solid colors in the real world.  Think about this for a moment.  There are a lot of colors that we perceive as being solid, but when we really look at them, there is some sort of variation (from top to bottom, from side to side, or from some arbitrary angle) based on how the light hits the object.  Because of this, we can add gradients to our applications to make them look more natural; they can also add a bit of visual interest as well.

Gradients in XAML
XAML makes it very easy to add a gradient.  All we need to do is create a gradient brush, and we have a couple of options for that: LinearGradientBrush and RadialGradientBrush.  The LinearGradientBrush lets us create gradients that move evenly from top to bottom, from left ot right, or from one side to another at whatever angle we choose.  The RadialGradientBrush starts at a point and radiates outward (you can think about this as the highlight that you see on the surface of a sphere).

When you create the gradient brush, you specify the gradient stops.  This is how you let XAML know where each color should be along the continuum.  If you've taken a look at my samples, you know that I have a particular gradient background that I always use.  (I'm not recommending this.  It's something that I'm used to that doesn't look too bad.)

Here's the gradient definition:

And what it looks like:

What this means: the start point is the starting point for our gradient.  In this case, we are using point "0,0" which is at the top-right of the control.  The end point "1,1" specifies the bottom-left corner.  So, we will end up with a diagonal gradient.  Next we have 2 or more gradient stops.  The offset value is a value between 0 and 1 to specify where the color should be.  In this case, the first gradient stop is at "0", meaning put Alice Blue at the beginning of the gradient (in this case, the top-right corner).  The second gradient stop is at "0.7" which you can translate as 70% across the gradient.  This point should be Steel Blue.  Since we do not have any additional gradient stops, this color will be "solid" through the end of the gradient.

The great thing about specifying gradients in XAML is that we just specify the gradient stops (where we want our "solid" colors to be).  The XAML renderer figures out how to make the smooth transition from one color to the next.

Gradients in the UI
Here's another example of an application that uses gradients as control backgrounds.  Note: this is an actual application that I wrote and deployed (but the names have been changed to protect the innocent).


Here you can see gradients in the header, the client area, and the login box.  One thing to note about these gradients is that they move from one color to a similar color.  In the case of the client area, it moves from "Ivory" to "Moccasin" and back to "Ivory".  The login box moves from "Steel Blue" to "Dark Blue" and back to "Steel Blue".

Here is the gradient that's used for the header and login box:


This is a little different from our previous gradient.  First, the start point and end point specify that this will be a gradient that goes from top to bottom.  This time we have 3 gradient stops.  The first one specifies Steel Blue at the start point.  The second specifies Dark Blue at the 90% mark.  The third goes back to Steel Blue at the 100% mark.  We can see this as the color moves gradually from Steel Blue (the lighter blue) to Dark Blue, and then quickly back to Steel Blue.
If we were to move from "Steel Blue" to "Orange", things would look a little strange.  Think about the gradients that we see in nature.  We see subtle differences in colors -- moving from white to gray, or from lemon yellow to a darker yellow.  If we create a jarring gradient, then it has the same effect as a rainbow wig -- attention getting, jarring, and unnatural.

Subtler Gradients
In addition to using gradients for control backgrounds, we can also use them more subtly.  Take a look at the following screenshot:


Can you tell how this differs from the screenshot above?  If you're anything like me, you can see a difference and maybe have a preference, but you have difficulty pointing out what the difference is.  Here's are side-by-side comparisons of the affected area:


The difference is that we applied a gradient to the text of the application name.  The great thing about XAML is that it makes this incredibly easy.  In fact, for this sample, we're using the same gradient for the header, the login box, and the application name.  This gradient is stored as an application resource in the App.xaml file.  This makes it easy to share across our screens (and also very easy to update if we change our design).

We'll be looking at this application in a little more detail in future posts.  At that point, we'll see a few more cool XAML features and how it can add value to our UI.

Happy Coding!

Saturday, February 25, 2012

XAML Namespaces and Default Properties

Here are a few questions that have come up during some recent "XAML: Don't Fear the Markup" presentations.

Question: How can you tell what is in the namespaces that are included by default in the XAML markup?

MSDN and the Visual Studio Help contain listings of the elements that are in the namespaces.  For example, the "x:" namespace (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml") is available in this article: XAML Namespace (x:) Language Features.  It's interesting to take a quick tour through this list.  It shows the "x:Class", "x:Name", and "x:Key" that were mentioned in the presentation; but it also shows things like "x:Null" which are useful for resetting a property that would normally be inherited.  For example, if you have a custom Style, you can choose to have that style automatically applied to all of the applicable controls in the XAML document.  If a control needs to use the default style rather than the custom style, you can set that control's style to "{x:Null}" to reset the value.

The other namespace that we looked at a little was the "d:" namespace (xmlns:d="http://schemas.microsoft.com/expression/blend/2008").  This also has an article describing the members: Design-Time Attributes in the Silverlight Designer.  This shows the "d:DesignHeight" and "d:DesignWidth" that we saw in the sample.  It also has some interesting things to look into further such as "d:DataContext" which lets you set up a design-time data context for data binding.  In our sample, the databinding was hooked up to a local object, so the design-time view worked without doing anything special.  But if you had remote data (for example, customer data coming from a SQL database), then you wouldn't have that data available at design time.  In that case, you could use the "d:DataContext" to hook up to a local object that had some sample hard-coded data.  These are all design-time functions.  They are there to help you with your XAML page/window/user control creation.  At run time, your actual data context would be used.

Question: The XAML namespaces use the URI format ("http://...").  How should you name your own namespaces?

When creating your own namespaces, you should follow whatever namespace naming convention that you have in place.  There is no need to use the URI format; instead, simply use the standard .NET namespace naming -- usually something like "CompanyName.Product.Module".  In the sample, we saw how to bring in a namespace that is local to our project, which ended up looking like this: xmlns:local="clr-namespace:JeremyBytes.StopWatch".  But it is fairly simple to bring in namespaces from other assemblies that are referenced in the current project.  You can get more information here: XAML Namespaces and Namespace Mapping for WPF XAML.

Question: How can you identify the default property of a XAML element?

The default property of a XAML element is the property that we can simply put "between the tags" without any specific references.  In our sample, we saw that we could specify the content property for a button by simply putting the content between the opening and closing tags: "<Button...>Start</Button>".  The question is how do we know which property is the default property?

The default properties are specified in the help file.  So, all we need to do is press "F1" on any of our controls to see what the value is.  Here are a few samples:



Here, we can see what the default properties are for each of these elements.  As we saw in the sample, we are always free to explicitly specify the property, but using the default property syntax can help keep our markup more readable.

If you have any questions about the XAML presentation or walkthrough, feel free to send them along to me.

Happy Coding!

Monday, February 20, 2012

San Diego .NET UI Developers SIG

For those of you in the San Diego area, I'll be speaking at the San Diego .NET UI Developers SIG tomorrow night (February 21, 2012).  Details are available here: San Diego .NET User Group.

The topic is XAML: Don't Fear the Markup.  We'll be getting comfortable with the XAML markup and see how we can tweak it to meet our UI needs.  In addition, we'll take a look at a few cool design tricks that we can use to add a little "glow" to our UI.  Hope to see you there.

Happy Coding!

Sunday, January 10, 2010

Introduction to XAML with WPF

(Editor's note: I will be presenting this topic at the SoCal Code Camp Jan 30 & 31, 2010.)

Overview
Understanding XAML (eXtensible Application Markup Language) is a key to creating the latest .NET user experiences in WPF and Silverlight. We will introduce the basic concepts around XAML and take a look at various features such as namespaces, elements, properties, events, attached properties and some basic layout. We’ll create a simple WPF application that covers these fundamentals. Although you will probably end up doing most of your UI design with a drag-and-drop tool such as Expression Blend, knowing the internals gives you a leg up in making the final tweaks to ensure an excellent user experience.

Get It Here
As mentioned in a previous post, the demos are now available in PDF form here: http://www.jeremybytes.com/Demos.aspx.

Direct Links:
PDF Walkthrough
Code Download

Happy coding!

Thursday, December 31, 2009

Introduction to the Background Worker Component in WPF

(Editor's Note: An updated and expanded version of this article is available for download: Keep Your UI Responsive with the Background Worker Component)

The Problem

We've all experienced it: the application UI that hangs. You get the dreaded "Not Responding" message, and you have to decide if you should wait it out or simply kill the process. If you have long-running processes in your application, you should consider putting them on a separate thread so that your UI remains responsive. However, threading is a daunting subject. We've heard horror stories about race conditions and deadlocks, and needing to use the thread dispatcher to communicate between background threads and UI threads. At this point, it sounds like a subject best left to the experts.

The Solution

Fortunately, the .NET framework provides a simple way to get started in threading with the BackgroundWorker component. This wraps much of the complexity between your background thread and your UI thread without doing any special coding. You can use this component with WinForms and WPF applications. We'll be using it with WPF here.

The BackgroundWorker offers several features which include spawning a background thread, the ability to cancel the background process before it has completed, and the chance to report the progress back to your UI. We'll be looking at all of these features.

The Set Up

We'll start with a fairly simple WPF application that has a long-running process that blocks the application until it has completed. You can download the source code for the application here: http://www.jeremybytes.com/Downloads.aspx. The download includes the starter application and the completed code. The starter application includes the following.

1. A Simple WPF form:


You can find the XAML for this in the download. It consists of 2 Text Boxes (Iterations and Output), a Progress Bar, and 2 Buttons (Start and Cancel).

2. A long-running process (in the code-behind the form):

(click image to enlarge)


You can see that we're using the famously slow process Sleep(100) that loops based on the parameter value.

3. Event-handlers for the buttons (in the code-behind):

(click image to enlarge)


When you run the application and click the Start button, you'll see that the application hangs until the process is finished. If you try to move or resize the window while the process is running, nothing will happen for several seconds. And you'll see the "Not Responding" message if you look in Task Manager:



When the process is completed, you will see the value from the Iterations box mirrored in the Output box. This is simply a confirmation that the process completed. You can try this with different values. Since we are using a Sleep(100), a value of 50 iterations will translate into a 5 second process; a value of 100 is 10 seconds, and so on. Just as a side note, I chose a value of 1/10th of a second for the Sleep rather than the usual 1 second so that we will have a smoother progress update later on.


Adding the BackgroundWorker

The BackgroundWorker is a non-visual component. In the WinForms world, this would mean that we could just drag the BackgroundWorker from the Tool Box onto the Form, and it would show up as a non-visual component. In WPF, things are a little bit different. We need to add the BackgroundWorker as a window resource that we can reference throughout our code. Here's the steps:

1. Add the System.ComponentModel namespace to the XAML. We do this in the markup for the Window. The good news is that Visual Studio IntelliSense helps you out quite a bit with this. We'll give the namespace a "cm" alias so we can reference it easily. Here's the Window markup with the namespace included:

(click image to enlarge)


2. Add a BackgroundWorker as a Window Resource.

(click image to enlarge)



Hooking Things Up

To use the basic functionality of the BackgroundWorker, we need to do a couple of things. First, we need to hook up two event handlers: DoWork and RunWorkerCompleted. These events are much like they sound. To kick off the background process we call the RunWorkerAsync method of the BackgroundWorker and pass any parameters needed. This fires the DoWork event (which is where we'll put our long-running process). The RunWorkerCompleted event fires after that process is done. At that point, we can update our UI and do clean up (if required).

So, let's put our process into the background. We'll start by creating the handlers for the events mentioned above. As a reminder, Visual Studio IntelliSense helps us out quite a bit with this. In our BackgroundWorker markup that we created above, just type "DoWork=" and you'll get the option for "New Event Handler". This will create the stub and give the handler a name based on our component. We'll do the same for "RunWorkerCompleted" and end up with the following XAML:

(click image to enlarge)


Now we'll flip over to the code-behind and implement these handlers. Let's look at the code, then we'll talk through it. Note, in addition to the code below, I have also added a "using System.ComponentModel;" to make things a little less verbose:

(click image to enlarge)


First, you'll see that our DoWork event calls the DoSlowProcess method (our long-running process). You'll note that we are getting an integer argument from the DoWorkEventArgs (we'll see how this gets passed in just a minute). The e.Argument is of type Object, so we have to cast it to the integer type that our method is expecting. Next, you'll note that we're passing the result back to the DoWorkEventArgs in e.Result. This will be used in the next handler.

The RunWorkerCompleted event fires after the long-running process is complete. You can see that the first thing we do is check to see if an error occurred. If not, then we'll go ahead and populate the output box with the result of our method. The e.Result here is actually the same e.Result from the DoWork event. In our case, the DoSlowProcess returns an integer that we populate in the output. In addition, you can see that we are enabling and disabling the buttons as appropriate.

The important thing is what you don't see. Notice that our completed handler is manipulating our UI elements without any use of the Dispatcher or Invoke methods that you need to do if you are handling the threading on your own. Instead, we just reference the elements on the UI thread directly. The BackgroundWorker takes care of all of the complexity on the back end.

Finally, we need to kick off the DoWork event in our Start Button handler. In order to do this, we need a reference to the BackgroundWorker component in our window. The problem is that it is simply a resource right now. The first task is to get a reference to it. We'll put this code at the top of our Window class and modify the constructor:

(click image to enlarge)


In this code, you see that we create a private variable to reference the BackgroundWorker component. Then in the constructor, we pull the component out of the resources by using the FindResource method. Now we can use the component in our code.

Here's our updated code in the Start Button Click event handler:

(click image to enlarge)


You'll notice that instead of calling the DoSlowProcess directly, we are now calling the RunWorkerAsync method of the BackgroundWorker. This method takes an optional object parameter. In our case, we will use this to pass the number of iterations through. This is the value that shows up in the e.Argument of the DoWork handler that we saw above.

The next thing we do is update the button states appropriately. Since the Cancel button is not yet implemented, it won't have too much effect. But we'll get to that in a bit.

Finally, note that we are clearing the output text. Remember that since we are running the process in the background, our UI still remains responsive. We want to clear out the output while the process is running, and then populate it agian after the process is complete. This is handled by the RunWorkerCompleted event that we saw above.

Now we have a fully-functional application with a background process. If you run the application now, you'll notice different behavior from what we saw before. After you click the Start button, the UI remains responsive: you can move and resize the window, type in the boxes, or whatever. When the process if finished, the output box is updated.

But we're not done yet. We still need to look at the Cancel and Progress functions.


Updating Progress

Next we'll look at reporting progress back from our long-running process. One thing to keep in mind if you want to have a progress bar in your UI: you will need to come up with some type of metric for the percent complete. For example, I have used the BackgroundWorker for long-running SQL queries. In this case, I was unable to report percentage because I had no idea exactly how long the process would take. In our sample here, we can use some fairly simple math to report the percentage completed.

The BackgroundWorker has a property we need to set (WorkerReportsProgress) and an event handler (ProgressChanged). These are fairly straight forward to implement. But here's where things get a little complicated. We need to update the progress in our DoSlowProcess method. This means that we need a reference to the BackgroundWorker.

Let's start with the easy parts. First the updated XAML:

(click image to enlarge)


Here we just set the WorkerReportsProgress to True (the default is False) and add the stub for the ProgressChanged event handler. As we did above, we'll just let Visual Studio create a New Event Handler for us.
To implement the event handler, we'll just set the value of the progress in our UI:

(click image to enlarge)


Now we'll make updates to some of our existing code. First, the DoSlowProcess method:

(click image to enlarge)


We've added both BackgroundWorker and DoWorkEventArgs parameters to the DoSlowProcess method. In order to update the progress, we'll add some code to each iteration of the loop. First, we check to make sure that the BackgroundWorker parameter was populated; then we check the WorkerReportsProgress property to see if the BackgroundWorker reports progress. If false, then we'll skip the code. If true, then we calculate the percentage and call the BackgroundWorker.ReportProgress method. This will fire the ProgressChanged event that we implemented above.

Now, since we've added additional parameters to DoSlowProcess, we'll need to update the method call. As a reminder, this was in the DoWork event. Here's the updated code:

(click image to enlarge)


We'll just cast the sender to a BackgroundWorker and pass it on through. We'll just pass the DoWorkEventArgs parameter through as well.

Finally, we'll add a line of code to the RunWorkerCompleted event to zero out the progress bar after it has completed:

(click image to enlarge)


The reason for this is if you are using Windows Vista or Windows 7, the progress bar continues to animate even after it is as 100%. This makes it difficult to tell that the progress is complete. So, we'll just set it back to 0 after it's done.


Now, if we run the application again, we'll see that we have a functional progress bar. The last step is to add cancellation.


Canceling the Background Process

Before implementing cancellation in your application, you will need to take a few things into consideration. First, when you cancel a BackgroundWorker process, there is no event that fires, and the process does not stop immediately. Instead, a cancellation flag gets set on the BackgroundWorker. It is up to your long-running process to check for this flag and to stop running if necessary. In my example above with the long-running SQL query, I could not implement cancellation because there was no "iteration" in my process -- it was simply waiting for the query to return.

In our example here, since we are using a loop, we have a perfect place to check for cancellation and stop our process. Here's an overview of the steps we'll take, then we'll look at each in more detail.

First, we need to set a property on the BackgroundWorker ("WorkerSupportsCancellation"). Then we'll tell the component we want to cancel in the Cancel Button event handler. Next we'll add the cancellation code to our DoSlowProcess method. And finally, we'll make a few changes to the RunWorkerCompleted event handler to behave differently if the process was canceled.

First, the XAML:

(click image to enlarge)

Next, the Cancel Button event handler:

(click image to enlarge)

You can see that we're simply calling the CancelAsync method of the BackgroundWorker.

Next, add the cancellation logic to the DoSlowProcess:

(click image to enlarge)

You can see that we added another conditional to check CancellationPending. If so, then we'll set the e.Cancel property of the DoWorkEventArgs and return from our method.

And finally, the RunWorkerCompleted:

(click image to enlarge)

Here, you can see that we are checking the e.Cancelled property of the EventArgs. If it's true, then we'll put "Canceled" in the output box. One thing you'll note: we are not resetting the progress bar in event of cancellation. This is so that if you stop the process, you can still see how far it got before the cancellation.



Now, when we run the application, we'll see that we have a long-running process that runs in the background (keeping the UI responsive), an updating progress bar, and a working Cancel button.


Wrap Up

The BackgroundWorker component allows us to put long-running processes onto a background thread without the usual complexities of threading. We have seen how we can get progress updates that we can show in our UI as well as how to cancel a process before it has completed. In addition, we've seen that even when updating our UI, we don't have to worry about communicating across threads. It is all handled for us in the component.

Probably the best thing about the BackgroundWorker is that it allows us to get our feet wet in the world of threading in an easy and relatively safe way. Think about this the next time you come across an application that is "Not Responding". And do what you can to keep your UIs responsive for your users.

Happy coding!