use Enum as an ItemsSource

Imagine we have an Enum type and we want to use that Enum type to be an ItemsSource of ListBox or ComboBox. Bolow is an example of an Enum type called AirFareBookingStatus

   1: public enum AirFareBookingStatus
   2: {
   3:     AlreadyPaid,
   4:     Cancelled,
   5:     Delayed,
   6:     Deleted,
   7:     InProcessing,
   8:     New
   9: }

What we want to achieve is to populate all the statuses from the Enum to a ListBox or ComboBox.

There is already a solution for this from the Silverlight forum. The idea is to go through all the Field and put them into a IEnumerable of KeyValuepair

   1: IEnumerable<KeyValuePair<string, AirFareBookingStatus>> results;

   2: var x = typeof(AirFareBookingStatus).GetFields().Where(info => info.FieldType.Equals(typeof(AirFareBookingStatus)));

   3: results = from field in x

   4:           select new KeyValuePair<string, AirFareBookingStatus>(field.Name, (AirFareBookingStatus) Enum.Parse(typeof(AirFareBookingStatus), field.Name, false));

Then all we have to do is assign the result to ListBox or ComboBox ItemsSource


   1: lstStatus.ItemsSource = results;

   2: cmbStatus.ItemsSource = results;


That would be good enough for it to work.

But we can even make it more generic by creating a helper function as below

   1: public static class Helper

   2: {

   3:     internal static IEnumerable<KeyValuePair<string, T>> GetEnumList<T>()

   4:     {

   5:         var x = typeof(T).GetFields().Where(info => info.FieldType.Equals(typeof(T)));

   6:         return from field in x

   7:                select new KeyValuePair<string, T>(field.Name, (T) Enum.Parse(typeof(T), field.Name, false));

   8:     }

   9: }

Then, we can call that function for every Enum type we have. For example

   1: lstStatus.ItemsSource = Helper.GetEnumList<AirFareBookingStatus>();

   2: cmbColors.ItemsSource = Helper.GetEnumList<ColorEnum>();

There is still one problem left we have. The item still displays the whole object, so make it display correctly, we need to create DataTemplate resource

   1: <DataTemplate x:Key="KeyValuePairDataTemplate">

   2:     <TextBlock Text="{Binding Key}" />

   3: </DataTemplate>

Then apply that DataTemplate to the ItemTemplate of ListBox or ComboBox as below

   1: <ListBox x:Name="lstStatus"

   2:     ItemTemplate="{StaticResource KeyValuePairDataTemplate}" />

   3:

   4: <ComboBox x:Name="cmbColors"

   5:     ItemTemplate="{StaticResource KeyValuePairDataTemplate}" />

That’s it. Hope that helps.

Continue …

Now, I have run into another problem. Doing that way above is all good, except the name won’t be as flexible. So, I am going to Description attribute to display data instead of the normal name of the Enum. To do that, I’ve changed a bit of my Enum like below

   1: public enum AirFareBookingStatus

   2: {

   3:     [Description("Already Paid")]

   4:     AlreadyPaid,

   5:     [Description("i am cancelled")]

   6:     Cancelled,

   7:     [Description("I got delayed")]

   8:     Delayed,

   9:     [Description("oh man i am about to be deleted")]

  10:     Deleted,

  11:     [Description("who is processing me")]

  12:     InProcessing,

  13:     [Description("I am brand new babe")]

  14:     New

  15: }


Next, I changed a bit in my helper function as well. It’ll get the Description attribute and make it to be Key

   1: internal static IEnumerable<KeyValuePair<string, T>> GetEnumList<T>()

   2:        {

   3:            var x = typeof(T).GetFields().Where(info => info.FieldType.Equals(typeof(T)));

   4:            return from field in x

   5:                   select new KeyValuePair<string, T>(GetEnumDescription(field), (T)Enum.Parse(typeof(T), field.Name, false));

   6:        }

   7:

   8: private static string GetEnumDescription(FieldInfo field)

   9:        {

  10:            DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);

  11:            if (attributes.Length > 0)

  12:            {

  13:                return attributes[0].Description;

  14:            }

  15:            else

  16:            {

  17:                return field.Name;

  18:            }

  19:        }

Finally, we will have something like this

Enum

That’s it. Let me know if you have any comments.

jQuery UI DatePicker: Disable Specified Days

jQuery UI DatePicker: Disable Specified Days

Written by David Walsh on Tuesday, January 26, 2010

jQuery Calendar Picker

One project I’m currently working on requires jQuery. The project also features a datepicker for requesting a visit to their location. jQuery UI’s DatePicker plugin was the natural choice and it does a really nice job. One challenge I encountered was the need to prevent specific days from being picked. Here’s the jQuery javascript I used to accomplish that.

The jQuery Javascript

/* create an array of days which need to be disabled */  var disabledDays = ["2-21-2010","2-24-2010","2-27-2010","2-28-2010","3-3-2010","3-17-2010","4-2-2010","4-3-2010","4-4-2010","4-5-2010"];    /* utility functions */  function nationalDays(date) {  	var m = date.getMonth(), d = date.getDate(), y = date.getFullYear();  	//console.log('Checking (raw): ' + m + '-' + d + '-' + y);  	for (i = 0; i < disabledDays.length; i++) {  		if(ArrayContains(disabledDays,(m+1) + '-' + d + '-' + y) || new Date() > date) {  			//console.log('bad:  ' + (m+1) + '-' + d + '-' + y + ' / ' + disabledDays[i]);  			return [false];  		}  	}  	//console.log('good:  ' + (m+1) + '-' + d + '-' + y);  	return [true];  }  function noWeekendsOrHolidays(date) {  	var noWeekend = jQuery.datepicker.noWeekends(date);  	return noWeekend[0] ? nationalDays(date) : noWeekend;  }    /* taken from mootools */  function ArrayIndexOf(array,item,from){  	var len = array.length;  	for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){  		if (array[i] === item) return i;  	}  	return -1;  }  /* taken from mootools */  function ArrayContains(array,item,from){  	return ArrayIndexOf(array,item,from) != -1;  }    /* create datepicker */  jQuery(document).ready(function() {  	jQuery('#date').datepicker({  		minDate: new Date(2010, 0, 1),  		maxDate: new Date(2010, 5, 31),  		dateFormat: 'DD, MM, d, yy',  		constrainInput: true,  		beforeShowDay: noWeekendsOrHolidays  	});  });  
Click here to copy this code to the clipboardClick here to add this snippet to CodaClick here to add this snippet to TextMateGet the raw code
1/* create an array of days which need to be disabled */
2var disabledDays = [“2-21-2010”,“2-24-2010”,“2-27-2010”,“2-28-2010”,“3-3-2010”,“3-17-2010”,“4-2-2010”,“4-3-2010”,“4-4-2010”,“4-5-2010”];
3
4/* utility functions */
5function nationalDays(date) {
6 var m = date.getMonth(), d = date.getDate(), y = date.getFullYear();
7 //console.log(‘Checking (raw): ‘ + m + ‘-‘ + d + ‘-‘ + y);
8 for (i = 0; i < disabledDays.length; i++) {
9 if(ArrayContains(disabledDays,(m+1) + ‘-‘ + d + ‘-‘ + y) || new Date() > date) {
10 //console.log(‘bad: ‘ + (m+1) + ‘-‘ + d + ‘-‘ + y + ‘ / ‘ + disabledDays[i]);
11 return [false];
12 }
13 }
14 //console.log(‘good: ‘ + (m+1) + ‘-‘ + d + ‘-‘ + y);
15 return [true];
16}
17function noWeekendsOrHolidays(date) {
18 var noWeekend = jQuery.datepicker.noWeekends(date);
19 return noWeekend[0] ? nationalDays(date) : noWeekend;
20}
21
22/* taken from mootools */
23function ArrayIndexOf(array,item,from){
24 var len = array.length;
25 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
26 if (array[i] === item) return i;
27 }
28 return 1;
29}
30/* taken from mootools */
31function ArrayContains(array,item,from){
32 return ArrayIndexOf(array,item,from) != 1;
33}
34
35/* create datepicker */
36jQuery(document).ready(function() {
37 jQuery(‘#date’).datepicker({
38 minDate: new Date(2010, 0, 1),
39 maxDate: new Date(2010, 5, 31),
40 dateFormat: ‘DD, MM, d, yy’,
41 constrainInput: true,
42 beforeShowDay: noWeekendsOrHolidays
43 });
44});

The base code is taken from this forum post. You’ll note that I created an array of dates in string format which also accommodates for comparing year.

I’d like to see jQuery UI implement a standard way of disabling days. Their DatePicker is very nice though so I can’t complain too much!

–>

Premium WordPress Themes

Follow via RSS Epic Discussion

Commenter Avatar January 26 / #
Mark says:

I have to admit, I wish Mootools came with such a wide variaty of UI plugins…

All and all, I think you accomplished your goal very well! Good stuff.

Reply

Commenter Avatar January 26 / #
Salih Gedik says:

Nice. But I rarely need jQ. Mootools FTW isn’t it?

Reply

Commenter Avatar January 26 / #
Simeon says:

Nice post! Can be easily expanded by populating he “disabledDays” using PHP to find all weekends, holidays, etc. I wonder what the performance impact is though if you span across several years as a typical selection might allow?

Reply

Commenter Avatar January 26 / #
Savageman says:

@mark: you should try this Mootools DatePicker (also works for time): http://www.monkeyphysics.com/mootools/script/2/datepicker

Doesn’t have a beforeShowDay option though…

Reply

Commenter Avatar January 26 / #

I would remove all the MooTools helpers🙂 and just use the jQuery native $.inArray function:

Change this line: ArrayContains(disabledDays,(m+1) + ‘-’ + d + ‘-’ + y) to this instead: $.inArray(disabledDays,(m+1) + ‘-’ + d + ‘-’ + y) != -1

Then you don’t need to two other functions from MooTools.

Reply

Commenter Avatar January 26 / #

@Douglas Neiner: Sorry, flip the arguments. $.inArray( value, array )

Reply

David Walsh January 26 / #

@Douglas Neiner: I’m a complete MooTools nerd — I didn’t even think to check the jQuery API. Will update.

Reply

Commenter Avatar January 26 / #

Interesting dilema and solution. My problem with the jQuery Datepicker is figuring out how to store selected start and end dates in a cookie.

Reply

Commenter Avatar January 26 / #
Brad Zickafoose says:

Is it possible to have the DatePicker block out today’s date as well as past dates from being selected, only allowing tomorrow and future dates available for selection?

Reply

Be Heard!

I want to hear what you have to say! Share your comments and questions below.

Silverlight Unit Testing Framework: Asynchronous Testing of Behaviors

Last month, I bogged about Unit Testing ViewModels AND Views using the Silverlight Unit Testing Framework. I wanted to take that post a step further and talk about some more advanced testing scenarios that are possible.

The site itself provides a lot of information about how to get started and what is available with the framework. One thing to keep in mind that is a radical shift from other testing frameworks is that the Silverlight testing framework runs on the UI thread. This means it does not spawn multiple threads for multiple tests and in fact requires the tests to run “one at a time” so they can take advantage of the test surface that is supplied.

This is a bit different than other frameworks but in my opinion, makes a lot of sense when dealing with Silverlight. The framework provides incredible flexibility for configuring and categorizing your tests.

If you are searching for a very comprehensive example of the framework in use, look no further than the Silverlight Toolkit. This comes with all source code and in fact uses the testing framework for its tests. You will find not only advanced scenarios for testing, but thousands upon thousands of tests! (I also am guessing that a new standard for PC performance has been invented by mistake … let’s all compile the entire toolkit and compare how long it takes!)

Tagging Tests

One thing you’ll find if you run the toolkit tests is that you can enter a tag to filter tests. For example, type in “Accordion” to only run the 800 or so unit tests for accordion-type controls.

To use tag functionality, simply “tag” your test like this:

1.[TestClass]
2.[Tag("MEF")]
3.public class PartModuleTest
4.{
5.}

I’ve tagged the test to be a MEF-related test. When I wire up the framework, I can filter the tag like this:

1.UnitTestSettings settings = UnitTestSystem.CreateDefaultSettings();
2.settings.TagExpression = "MEF";
3.this.RootVisual = UnitTestSystem.CreateTestPage(settings); 

When I run the tests, only my tests tagged with MEF will run! The toolkit provides an example of a UI that allows you to select the tag, then run the test.

Asynchronous Tests

It is often necessary to test methods that are asynchronous or require event coordination. An example may be a service that must wait on return values, or a user control that must be loaded into the framework before you can test it. The Silverlight Unit Testing Framework provides the Asynchronous tag to facilitate this type of test. This tells the framework not to move onto the next test nor consider the current test method complete until an explicit call to TestComplete is made.

There are several “helper” methods supplied for asynchronous processing that we’ll explore in a minute. To use these methods requires inheriting from one of the base test classes such as SilverlightTest which provides the methods as well as the test surface to add controls to.

In PRISM, MEF, and MVVM Part 1 of 3: Unity Glue I explored various options for binding the view model to the view. The 3rd and final method I reviewed was using an attached behavior. I would like to write some unit tests for that behavior (indeed, if I were a test-driven development or TDD purist, I would have written those tests first).

In order to test the behavior, I need to attach it to a FrameworkElement and then validate it has done what I expected it to do. But how do I go about doing that in our unit test environment?

Attached Behaviors

Similar to other controls in other frameworks, Silverlight controls have a distinct life cycle. It varies slightly depending on whether the control has been generated in XAML or through code. There is a great summary table of these events on Dave’s Blog. What’s important to note is that values and properties are set as soon as you, well, set them, but bindings don’t take effect until they are inserted into the visual tree. In XAML, the XAML node becomes part of the tree and fires the Loaded event once it is fully integrated. In code, this happens after the element is added as the child of some other element that is in the tree. This allows Silverlight to parse the hierarchy and propagate dependency properties.

So what we essentially want to do is take our behavior, attach it to an element, and then wait for the Loaded event to fire so we can inspect the element and see that it has been modified accordingly (in this case, we expect that the DataContext property has been set to our view model).

Setting up the Project

The testing framework provides some handy templates for getting started. I add a new project and select the Silverlight Test Project template. I then add references to the projects I’ll be testing and the supporting frameworks like PRISM and MEF.

Next, I’ll want to build some helper classes to help me test my functionality.

Helper Classes

I like to create a folder called Helper and place my stubs, mocks, and other helper classes there. These may be utilities, like the Exception Expected utility I use, or classes that are used for the testing framework.

First, I’ll create a test view model with a simple string and string collection property for testing:

01.public class TestViewModel
02.{
03.    public TestViewModel()
04.    {
05.        ListOfItems = new List<string>();
06.    }
07. 
08.    public TestViewModel(List<string> items)
09.    {
10.        ListOfItems = items;           
11.    }
12. 
13.    public string Property { get; set; }
14. 
15.    public List<string> ListOfItems { get; set; }
16.}

If my view models have common methods described in a base class or interface, I might use a mocking framework to mock the class instead.

The Test Class

The behavior I created has an affinity to the Unity inversion of control (IoC) container. It could be refactored otherwise, but it made sense for the sake of the demonstration. Therefore, I’ll need to have a container for testing, as well as the view model. My test class starts out looking like this (notice I base it on SilverlightTest):

01.[TestClass]
02.public class ViewModelBehaviorTest : SilverlightTest
03.{
04.    const string TESTPROP = "Test Property";
05. 
06.    IUnityContainer _container;
07. 
08.    TestViewModel _viewModel;
09. 
10.    [ClassInitialize]
11.    public void ClassInitialize()
12.    {
13.        _container = new UnityContainer();
14. 
15.        _viewModel = new TestViewModel() { Property = TESTPROP };
16.        _container.RegisterInstance<TestViewModel>(_viewModel);
17. 
18.        ViewModelBehavior.Container = _container;
19.    }
20.}

I create a reference to the entire test class for the container and the test view model. When the class is initialized (this is one-time setup, before all tests are run) I create a container, a view model, and tell the container that anytime someone asks for the view model, give them the specific instance I created. I also set the container on the type for the view model behavior class, so it knows what to use when resolving the view model.

The Code Behind Test

For my first test, I’ll programmatically attach the behavior and test that it works. The view model behavior takes in a string that is the fully qualified type name for the view model, and then uses the unity container to resolve it. Therefore, my test looks like this:

01.[TestMethod]
02.[Asynchronous]
03.[Description("Test creating an element and attaching in code behind.")]
04.public void TestAttach()
05.{
06.    TextBlock textBlock = new TextBlock();
07.    textBlock.SetValue(ViewModelBehavior.ViewModelProperty, typeof(TestViewModel).AssemblyQualifiedName);
08.                 
09.    textBlock.Loaded += (o, e) =>
10.    {
11.        Assert.IsNotNull(textBlock.DataContext, "The data context was never bound.");
12.        Assert.AreSame(textBlock.DataContext, _viewModel, "The data context was not bound to the correct view model.");
13. 
14.        EnqueueTestComplete();
15.    };
16. 
17.    TestPanel.Children.Add(textBlock);                                 
18.}

There’s a few things going on here, so let’s break them down!

The TestMethod attribute tags this method to be run by the framework. It is decorated with a description, which I can view on the output when the test is run and helps make the test more, ah, descriptive. The first thing I do is create a test block and attach the view model property. Here, I’m taking the test view model and getting the fully qualified name and using that to set the attached property. We want to make sure everything works fine and there are no errors during binding, so this is where the asynchronous pieces come into play.

The Asynchronous tag tells the framework that we’re waiting on events, so don’t consider this test complete until we explicitly tell the framework it’s complete. When the text block fires the Loaded event, we confirm that the data context is not null and that it in fact contains the exact instance of the view model we created in the class initialization. Then we tell the framework the test is complete by calling EnqueueTestComplete, which is provided by the base class.

Finally, if you were to run this without the last line, the test would stall because the text block would never get loaded. We add it as a child of the test surface, and this injects it into the visual tree and fires the loaded event.

The XAML Test

I’m not completely confident with this test because the whole reason for creating a behavior was so I could attach the view model in XAML and not use code behind. Therefore, I should really test attaching this behavior through XAML. So, at the top of the test class we’ll create the necessary XAML and wrap it in a UserControl:

01.const string TESTXAML =
02.    "<UserControl " +
04.        "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " +
05.        "xmlns:vm=\"clr-namespace:PRISMMEF.Common.Behavior;assembly=PRISMMEF.Common\">" +
06.            "<Grid x:Name=\"LayoutRoot\" Background=\"White\" " +
07.                "vm:ViewModelBehavior.ViewModel=\"PRISMMEF.Tests.Helper.TestViewModel, PRISMMEF.Tests, Version=1.0.0.0\">" +
08.                "<ListBox x:Name=\"ListBox\" ItemsSource=\"{Binding ListOfItems}\"/>" +
09.    "</Grid></UserControl>";

If you think the constant is ugly, you can always add an actual XAML file, set it as an embedded resource, then read it in instead. That would give you the full functionality of the editor to tweak the test code. Here, we simply create a control with a grid and a list box. The list box uses the attached behavior and also binds the list.

I want to test the list binding as well, so I add a collection to my test class:

1..
2.private static readonly List<string> _testCollection = new List<string> { "test1", "test2" };        
3..

In the class initialize method, I’ll pass this into the view model’s constructor so it is set on the ListOfItems property.

Now, we can create the control from XAML, load it, and test it:

01.[TestMethod]
02.[Asynchronous]
03.[Description("Test creating from XAML")]
04.public void TestFromXaml()
05.{
06.    UserControl control = XamlReader.Load(TESTXAML) as UserControl;
07.     
08.    control.Loaded += (o, e) =>
09.    {
10.        ListBox listBox = control.FindName("ListBox") as ListBox;
11. 
12.        Assert.IsNotNull(listBox, "ListBox was not found.");
13.        Assert.IsNotNull(listBox.DataContext, "The data context was never bound.");
14.        Assert.AreSame(listBox.DataContext, _viewModel, "The data context was not bound to the correct view model.");
15. 
16.        IEnumerable<string> list = listBox.ItemsSource as IEnumerable<string>;
17.        List<string> targetList = new List<string>(list);
18.        CollectionAssert.AreEquivalent(targetList, _testCollection, "Collection not properly bound.");
19. 
20.        EnqueueTestComplete();
21.    };
22. 
23.    TestPanel.Children.Add(control);          
24. }

Now we load the control from XAML and wire in the Loaded event to test for the data context and the instance. Then, I take the items from the list box itself and compare them with the original list using CollectionAssert. The AreEquivalent does a set comparison. Then we signal the test is complete.

There’s no code for this example because it was very straightforward and I’ll likely be posting a more comprehensive example in the future as the result of a talk I’ll be giving. Be sure to tune into MSDN’s geekSpeak on Wednesday, February 17th, 2010 when I will be the guest to cover exclusively the topic of the Silverlight Unit Testing Framework (the talks are all stored on the site in case you read this after the event).

Thanks!

Jeremy Likness

Silverlight Unit Testing Framework: Asynchronous Testing of Behaviors

Last month, I bogged about Unit Testing ViewModels AND Views using the Silverlight Unit Testing Framework. I wanted to take that post a step further and talk about some more advanced testing scenarios that are possible.

The site itself provides a lot of information about how to get started and what is available with the framework. One thing to keep in mind that is a radical shift from other testing frameworks is that the Silverlight testing framework runs on the UI thread. This means it does not spawn multiple threads for multiple tests and in fact requires the tests to run “one at a time” so they can take advantage of the test surface that is supplied.

This is a bit different than other frameworks but in my opinion, makes a lot of sense when dealing with Silverlight. The framework provides incredible flexibility for configuring and categorizing your tests.

If you are searching for a very comprehensive example of the framework in use, look no further than the Silverlight Toolkit. This comes with all source code and in fact uses the testing framework for its tests. You will find not only advanced scenarios for testing, but thousands upon thousands of tests! (I also am guessing that a new standard for PC performance has been invented by mistake … let’s all compile the entire toolkit and compare how long it takes!)

Tagging Tests

One thing you’ll find if you run the toolkit tests is that you can enter a tag to filter tests. For example, type in “Accordion” to only run the 800 or so unit tests for accordion-type controls.

To use tag functionality, simply “tag” your test like this:

1.[TestClass]
2.[Tag("MEF")]
3.public class PartModuleTest
4.{
5.}

I’ve tagged the test to be a MEF-related test. When I wire up the framework, I can filter the tag like this:

1.UnitTestSettings settings = UnitTestSystem.CreateDefaultSettings();
2.settings.TagExpression = "MEF";
3.this.RootVisual = UnitTestSystem.CreateTestPage(settings); 

When I run the tests, only my tests tagged with MEF will run! The toolkit provides an example of a UI that allows you to select the tag, then run the test.

Asynchronous Tests

It is often necessary to test methods that are asynchronous or require event coordination. An example may be a service that must wait on return values, or a user control that must be loaded into the framework before you can test it. The Silverlight Unit Testing Framework provides the Asynchronous tag to facilitate this type of test. This tells the framework not to move onto the next test nor consider the current test method complete until an explicit call to TestComplete is made.

There are several “helper” methods supplied for asynchronous processing that we’ll explore in a minute. To use these methods requires inheriting from one of the base test classes such as SilverlightTest which provides the methods as well as the test surface to add controls to.

In PRISM, MEF, and MVVM Part 1 of 3: Unity Glue I explored various options for binding the view model to the view. The 3rd and final method I reviewed was using an attached behavior. I would like to write some unit tests for that behavior (indeed, if I were a test-driven development or TDD purist, I would have written those tests first).

In order to test the behavior, I need to attach it to a FrameworkElement and then validate it has done what I expected it to do. But how do I go about doing that in our unit test environment?

Attached Behaviors

Similar to other controls in other frameworks, Silverlight controls have a distinct life cycle. It varies slightly depending on whether the control has been generated in XAML or through code. There is a great summary table of these events on Dave’s Blog. What’s important to note is that values and properties are set as soon as you, well, set them, but bindings don’t take effect until they are inserted into the visual tree. In XAML, the XAML node becomes part of the tree and fires the Loaded event once it is fully integrated. In code, this happens after the element is added as the child of some other element that is in the tree. This allows Silverlight to parse the hierarchy and propagate dependency properties.

So what we essentially want to do is take our behavior, attach it to an element, and then wait for the Loaded event to fire so we can inspect the element and see that it has been modified accordingly (in this case, we expect that the DataContext property has been set to our view model).

Setting up the Project

The testing framework provides some handy templates for getting started. I add a new project and select the Silverlight Test Project template. I then add references to the projects I’ll be testing and the supporting frameworks like PRISM and MEF.

Next, I’ll want to build some helper classes to help me test my functionality.

Helper Classes

I like to create a folder called Helper and place my stubs, mocks, and other helper classes there. These may be utilities, like the Exception Expected utility I use, or classes that are used for the testing framework.

First, I’ll create a test view model with a simple string and string collection property for testing:

01.public class TestViewModel
02.{
03.    public TestViewModel()
04.    {
05.        ListOfItems = new List<string>();
06.    }
07. 
08.    public TestViewModel(List<string> items)
09.    {
10.        ListOfItems = items;           
11.    }
12. 
13.    public string Property { get; set; }
14. 
15.    public List<string> ListOfItems { get; set; }
16.}

If my view models have common methods described in a base class or interface, I might use a mocking framework to mock the class instead.

The Test Class

The behavior I created has an affinity to the Unity inversion of control (IoC) container. It could be refactored otherwise, but it made sense for the sake of the demonstration. Therefore, I’ll need to have a container for testing, as well as the view model. My test class starts out looking like this (notice I base it on SilverlightTest):

01.[TestClass]
02.public class ViewModelBehaviorTest : SilverlightTest
03.{
04.    const string TESTPROP = "Test Property";
05. 
06.    IUnityContainer _container;
07. 
08.    TestViewModel _viewModel;
09. 
10.    [ClassInitialize]
11.    public void ClassInitialize()
12.    {
13.        _container = new UnityContainer();
14. 
15.        _viewModel = new TestViewModel() { Property = TESTPROP };
16.        _container.RegisterInstance<TestViewModel>(_viewModel);
17. 
18.        ViewModelBehavior.Container = _container;
19.    }
20.}

I create a reference to the entire test class for the container and the test view model. When the class is initialized (this is one-time setup, before all tests are run) I create a container, a view model, and tell the container that anytime someone asks for the view model, give them the specific instance I created. I also set the container on the type for the view model behavior class, so it knows what to use when resolving the view model.

The Code Behind Test

For my first test, I’ll programmatically attach the behavior and test that it works. The view model behavior takes in a string that is the fully qualified type name for the view model, and then uses the unity container to resolve it. Therefore, my test looks like this:

01.[TestMethod]
02.[Asynchronous]
03.[Description("Test creating an element and attaching in code behind.")]
04.public void TestAttach()
05.{
06.    TextBlock textBlock = new TextBlock();
07.    textBlock.SetValue(ViewModelBehavior.ViewModelProperty, typeof(TestViewModel).AssemblyQualifiedName);
08.                 
09.    textBlock.Loaded += (o, e) =>
10.    {
11.        Assert.IsNotNull(textBlock.DataContext, "The data context was never bound.");
12.        Assert.AreSame(textBlock.DataContext, _viewModel, "The data context was not bound to the correct view model.");
13. 
14.        EnqueueTestComplete();
15.    };
16. 
17.    TestPanel.Children.Add(textBlock);                                 
18.}

There’s a few things going on here, so let’s break them down!

The TestMethod attribute tags this method to be run by the framework. It is decorated with a description, which I can view on the output when the test is run and helps make the test more, ah, descriptive. The first thing I do is create a test block and attach the view model property. Here, I’m taking the test view model and getting the fully qualified name and using that to set the attached property. We want to make sure everything works fine and there are no errors during binding, so this is where the asynchronous pieces come into play.

The Asynchronous tag tells the framework that we’re waiting on events, so don’t consider this test complete until we explicitly tell the framework it’s complete. When the text block fires the Loaded event, we confirm that the data context is not null and that it in fact contains the exact instance of the view model we created in the class initialization. Then we tell the framework the test is complete by calling EnqueueTestComplete, which is provided by the base class.

Finally, if you were to run this without the last line, the test would stall because the text block would never get loaded. We add it as a child of the test surface, and this injects it into the visual tree and fires the loaded event.

The XAML Test

I’m not completely confident with this test because the whole reason for creating a behavior was so I could attach the view model in XAML and not use code behind. Therefore, I should really test attaching this behavior through XAML. So, at the top of the test class we’ll create the necessary XAML and wrap it in a UserControl:

01.const string TESTXAML =
02.    "<UserControl " +
04.        "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " +
05.        "xmlns:vm=\"clr-namespace:PRISMMEF.Common.Behavior;assembly=PRISMMEF.Common\">" +
06.            "<Grid x:Name=\"LayoutRoot\" Background=\"White\" " +
07.                "vm:ViewModelBehavior.ViewModel=\"PRISMMEF.Tests.Helper.TestViewModel, PRISMMEF.Tests, Version=1.0.0.0\">" +
08.                "<ListBox x:Name=\"ListBox\" ItemsSource=\"{Binding ListOfItems}\"/>" +
09.    "</Grid></UserControl>";

If you think the constant is ugly, you can always add an actual XAML file, set it as an embedded resource, then read it in instead. That would give you the full functionality of the editor to tweak the test code. Here, we simply create a control with a grid and a list box. The list box uses the attached behavior and also binds the list.

I want to test the list binding as well, so I add a collection to my test class:

1..
2.private static readonly List<string> _testCollection = new List<string> { "test1", "test2" };        
3..

In the class initialize method, I’ll pass this into the view model’s constructor so it is set on the ListOfItems property.

Now, we can create the control from XAML, load it, and test it:

01.[TestMethod]
02.[Asynchronous]
03.[Description("Test creating from XAML")]
04.public void TestFromXaml()
05.{
06.    UserControl control = XamlReader.Load(TESTXAML) as UserControl;
07.     
08.    control.Loaded += (o, e) =>
09.    {
10.        ListBox listBox = control.FindName("ListBox") as ListBox;
11. 
12.        Assert.IsNotNull(listBox, "ListBox was not found.");
13.        Assert.IsNotNull(listBox.DataContext, "The data context was never bound.");
14.        Assert.AreSame(listBox.DataContext, _viewModel, "The data context was not bound to the correct view model.");
15. 
16.        IEnumerable<string> list = listBox.ItemsSource as IEnumerable<string>;
17.        List<string> targetList = new List<string>(list);
18.        CollectionAssert.AreEquivalent(targetList, _testCollection, "Collection not properly bound.");
19. 
20.        EnqueueTestComplete();
21.    };
22. 
23.    TestPanel.Children.Add(control);          
24. }

Now we load the control from XAML and wire in the Loaded event to test for the data context and the instance. Then, I take the items from the list box itself and compare them with the original list using CollectionAssert. The AreEquivalent does a set comparison. Then we signal the test is complete.

There’s no code for this example because it was very straightforward and I’ll likely be posting a more comprehensive example in the future as the result of a talk I’ll be giving. Be sure to tune into MSDN’s geekSpeak on Wednesday, February 17th, 2010 when I will be the guest to cover exclusively the topic of the Silverlight Unit Testing Framework (the talks are all stored on the site in case you read this after the event).

Thanks!

Jeremy Likness