Why XAML and Why SketchFlow for Prototyping–in Sketch!


No worries, no reading required.  If you are wondering why Microsoft came up with XAML (the eXtensible Markup Language) with the release of .NET framework 3.0 – which included Windows Presentation Foundation and Silverlight – then this sketch will help you understand that in 14 mins.  This is my try to explain the rational behind XAML and designer/developer concerns using a sketch.  Also, it has a glimpse of why prototyping is important and how SketchFlow (which is part of Expression Blend) addresses this important stage of system and UX design and development.

This is part of a session I delivered in TechEd MiddleEast 2010 which you can watch in full here: Prototyping the UX: Expression Blend + SketchFlow.

Behaviors – Busy State Indicator


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:

  1. Visual Studio 2010 Beta, you can download it from here.  VS 2008 should be fine as well.
  2. 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.

   1: namespace Behaviors101

   2: {

   3:     class BusyState

   4:     {

   5:         private bool isBusy;

   6:         private string text;

   7:  

   8:         public bool IsBusy 

   9:         {

  10:             get { return isBusy; }

  11:             set { isBusy = value; }

  12:         }

  13:  

  14:         public string BusyText 

  15:         {

  16:             get { return text; } 

  17:             set { text = value; }

  18:         }

  19:     }

  20: }

 

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:

   1: <Window

   2:         ...

   3:         xmlns:local="clr-namespace:Behaviors101"

   4:     

   5:         Title="MainWindow" Height="350" Width="525">

   6:  

   7:     <Window.Resources>

   8:         <!-- Instantiates the BusyState class -->

   9:         <!-- Giving it an x:Key so it's available as a resource -->

  10:         <local:BusyState x:Key="BusyStateObject" IsBusy="False" Text="None"/>

  11:     </Window.Resources>

  12:  

  13:     <Grid>

  14:         ...

  15:     </Grid>

  16: </Window>

 

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. 

   1: DispatcherTimer tmr;    

   2:     

   3: public MainWindow()

   4: {

   5:     InitializeComponent();

   6:  

   7:     // create the timer

   8:     tmr = new DispatcherTimer();

   9:     // set the interval to 5 seconds

  10:     tmr.Interval = TimeSpan.FromSeconds(5);

  11:     // wire the event of the timer tick

  12:     tmr.Tick += new EventHandler(tmr_Tick);

  13:     // start the timer

  14:     tmr.Start();

  15: }

  16:  

  17: // timer tick event which simply switched the application from busy to free to busy, ...

  18: void tmr_Tick(object sender, EventArgs e)

  19: {

  20:     // get a reference to the busy state object decalred in XAML as a resource

  21:     BusyState bstate = (BusyState)this.FindResource("BusyStateObject");

  22:  

  23:     // toggle the IsBusy

  24:     bstate.IsBusy = !bstate.IsBusy;

  25:     

  26:     // set the busy text to Busy or Free according to the busy flag

  27:     if (bstate.IsBusy)

  28:     {

  29:         bstate.BusyText = "Busy!";

  30:     }

  31:     else

  32:     {

  33:         bstate.BusyText = "Free...";

  34:     }

  35: }

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.

   1: <Grid>

   2:    <TextBlock Height="30" Margin="72,68,218,213" 

   3:         Text="{Binding Source={StaticResource BusyStateObject}, Path=BusyText}" />

   4:    <CheckBox Content="Is Busy?" Height="16" Margin="72,34,0,0" Name="checkBox1" Width="120" 

   5:         IsChecked="{Binding Source={StaticResource BusyStateObject}, Path=IsBusy}" />

   6: </Grid>

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:

   1: namespace Behaviors101

   2: {

   3:     class BusyState : INotifyPropertyChanged

   4:     {

   5:         private bool isBusy;

   6:         private string text;

   7:  

   8:         // Declare the event

   9:         public event PropertyChangedEventHandler PropertyChanged;

  10:  

  11:         public bool IsBusy 

  12:         {

  13:             get { return isBusy; }

  14:             set {

  15:                 isBusy = value;

  16:                 // Call OnPropertyChanged whenever the property IsBusy is updated

  17:                 OnPropertyChanged("IsBusy");

  18:             }

  19:         }

  20:       

  21:         public string BusyText 

  22:         {

  23:             get { return text; } 

  24:             set {

  25:                 text = value;

  26:                 // Call OnPropertyChanged whenever the property Text is updated

  27:                 OnPropertyChanged("BusyText");

  28:             }

  29:         }

  30:  

  31:         // Create the OnPropertyChanged method to raise the event

  32:         private void OnPropertyChanged(string p)

  33:         {

  34:             PropertyChangedEventHandler handler = PropertyChanged;

  35:             if (handler != null)

  36:             {

  37:                 handler(this, new PropertyChangedEventArgs(p));

  38:             }

  39:         }

  40:     }

  41: }

 

with that, go ahead and run your application and see how that the textblock and checkbox change values every 5 seconds.

image

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.

image

  • 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).

   1: <Grid

   2:    DataContext="{Binding Source={StaticResource BusyStateObject}}"

   3:    local:BusyIndicatorBehavior.BusyState="{Binding IsBusy}"

   4:    local:BusyIndicatorBehavior.TargetVisual="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type Grid}}}">

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.

image

In Summary:

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.

Blog at WordPress.com.
Theme: Esquire by Matthew Buchanan.

Follow

Get every new post delivered to your Inbox.