Hi again in the second part of discovering Behaviors in WPF/Silverlight with Expression Blend. In the previous part, we have seen how to build simple behaviors in code using Visual Studio 2010. In this post, I’m going to extend that and see how to use a “busy state indicator” as a behavior to signal the state of business in your application.
The other day, I was trying to include a busy indicator in my application. I didn’t want to build this from scratch, and instead wanted to use one of the behaviors available online. I found one in the Expression Community Gallery that is called Busy State Indicator Behavior by Pedro Pombeiro. This one is great since it is built as a reusable behavior, customizable, and makes use of a great indicator built by Sasha Barber, a Circular Progress Bar. Both form a perfect match of what I want. Details of how to use that in an application follow in this post.
Setting the stage:
In order for us to be on the same page, make sure you have the following in place:
- Visual Studio 2010 Beta, you can download it from here. VS 2008 should be fine as well.
- Download Busy State Indicator Behavior from here.
Building an application that uses Busy State Indicator Behavior:
1. Create a project in Visual Studio:
Give the project a name, I have named my project Behaviors101.
2. Build the busy state context:
I mean by that the logic needed to indicate when you’re application is busy. I will build that as a custom class in my project, which will provide two properties (IsBusy and BusyText) designating flag for business and an optional text for elaboration on what your application is busy on. Below is the initial code for this class that I have named BusyState.cs.
3. Use the busy state context in your application:
This step is more of just a reference and instantiation of the BusyState class outlined above. You can do that either in code or XAML. I have chosen to do that in XAML and made that possible by referencing the namespace of my application to get access to the BusyState class:
4. Build the functionality to use the busy state context:
Since I don’t have a functionality for this application, I’m gonna resemble its state of being busy by a timer. The timer will signal the application from busy to free upon the ticks of the clock. You may change that with your own logic such as asynchronous internet connections, database queries, or any other long running processes. Below is the code snippet that declares the timer, initializes it, and wires the event of ticking.
Notice how I have obtained a reference to the static resource BusyStateObject in line 21, which enables me then to change the busy flag and text.
5. Test out your application busy state by binding to UI
Before we go ahead with the behavior, let’s do a quick test on the above. I’m gonna bind the BusyStateObject with two elements in the UI in XAML: a textblock and a checkbox. This will enable us to do a quick check on whether the above is working.
The binding as you can see (in line 3 and 5) is simple: Text property (target property) of the TextBlock (target object) gets its value from the static resource defined above as BusyStateObject (source object) with a path to BusyText (source property). Same goes for IsChecked of the CheckBox.
Once you do this in XAML, you’ll see that design time immediately reflects on the BusyStateObject properties by setting IsChecked to false and Text to “None”. Now, if you run the application (F5) you will expect that the binding will do the job once the timer kicks in. Unfortunately that is not the case!
Although the timer does its job, you’ll find that changes to your BusyStateObject properties (IsBusy and Text) doesn’t have an effect on the UI and the bound properties, and that is caused by the fact that your application has no clue at all of the changes on those properties. Looking around for a solution will guide you to this article (WPF Basic Data Binding FAQ). In this article, you’ll see a solution to this problem which is all about implementing a notification (with events) when property values change by letting your class implement the interface INotifyPropertyChanged. The code changes to BusyState.cs conclude it as follows:
with that, go ahead and run your application and see how that the textblock and checkbox change values every 5 seconds.
6. Importing the Busy State Indicator Behavior:
The previous step enabled us to test out the application busy state and making sure everything is working fine. Of course the goal is to use a better busy state indicator UI instead of the the checkbox and textblock, so we’ll now use the BusyStateIndicator Behavior.
If you have successfully downloaded the behavior from the gallery, you’ll see that you have two components (3 files in total):
- CircularProgressBar (XAML and CS files): this is the artistic work which shows a bar of circles moving in a circular fashion. This is built by Sasha Barber and more information can be obtained here.
- BusyIndicatorBehavior (CS file): which is the behavior that uses the progress bar (notice the using Progress statement in the code). It implements a number of dependency properties that enable you to bind to. It also gives you control of the behavior such as dimming the application, the target visual, … This work is by Pedro Pombeiro and more information can be obtained from here.
With that, all you need to do is to include those files into your project, and reference the BusyStateIndicator behavior namespace in XAML. I have renamed the namespace in the imported files to Behaviors101 to make it simpler for me to reuse the previously used xmlns:local reference.
7. Using the BusyStateIndicator Behavior:
Now all files are imported to your project and referenced properly, you only need to look for the grid you want to target for the busy state behavior and attach the behavior. Also, you need to bind the BusyState property of the behavior to the whatever tells it to go busy (BusyStateObject.IsBusy is the one in our case).
Notice how that I have set the DataContext for data binding to the static resource BusyStateObject in line 2. Then I have used simple binding in line 3 to bind BusyState of the behavior (the target property) to IsBusy (the source property). In line 4, TargetVisual is bound to a relative source which is the Grid in this case.
Run the application now, and you’ll see that the circular bar fades in whenever the timer ticks, and gradually fades out on the next tick.
We have learned in this post how to use the BusyStateIndicator behavior and the attached Circular Progress Bar. The idea was to reuse an existing behavior available from the Expression Community Gallery, and setting the stage for using it with a busy state object/flag. A future post will utilize this behavior in a more practical way, but I wanted to detail the steps for you to use in your projects leveraging WPF and behaviors.