Thursday, January 6, 2011

[2011.01.06] Drag and Drop in WPF using MVVMLight [IV/IV]


downloadCode02
This is a multipart series outlining several topics is WPF.
  1. Part 1: MVVM via the MVVMLight framework
  2. Part 2: Drag and Drop
  3. Part 3: The Adorner
  4. Part 4: DataTemplateSelector, StyleSelector, Unit Testing

In this final part, I will outline some other features that supplement the application and provides a better user experience. This was done primarily as a demonstration of the features, namely DataTemplateSelector and StyleSelector.

The Data Template Selector

You use a DataTemplateSelector to display data from the same collection differently, based on some criteria in the data. For example, the Contact type has a property, Crew, which is a Faction enumeration. Please take a look at the Contact class in the code to download to see the definitions. In this case, I will use different DataTemplates based on which Faction each member belongs to. The different templates are defined in the ResourceDictionary1.xaml file.
You need to inherit from from the DataTemplateSelector base class and override the SelectTemplate() method. This is all illustrated in Listing 1.

1 using System.Windows;
2 using System.Windows.Controls;
3 using DragDropUsingMvvmLight01.Model;
4
5 namespace DragDropUsingMvvmLight01
6 {
7 /// <summary>
8 /// Extended class used to change the data template of each ListBoxItem based on some custom requirement.
9 /// </summary>
10 public class FactionDataTemplateSelector : DataTemplateSelector
11 {
12 public override DataTemplate SelectTemplate(object item, DependencyObject container)
13 {
14 var frameworkElement = container as FrameworkElement;
15
16 if (frameworkElement !=null && item is Contact )
17 {
18 Contact contact = item as Contact; // Contact is the type hosted in each ListBoxItem
19
20 if (contact.Crew == Faction.Strawhat)
21 return (DataTemplate)frameworkElement.TryFindResource("SourceListBoxItemTemplate");
22 return (DataTemplate)frameworkElement.TryFindResource("SourceListBoxDataTemplate02");
23 }
24 return null;
25 }
26 }
27 }
Listing 1: Implementation of a DataTemplateSelector

The Style Selector

The reason and strategy follows the same pattern as in the template selector case, so I will just add the code to Listing 2 and let you take it from there.
1 using System.Windows;
2 using System.Windows.Controls;
3 using DragDropUsingMvvmLight01.Model;
4
5 namespace DragDropUsingMvvmLight01
6 {
7 /// <summary>
8 /// Extended class used to change the style of each ListBoxItem based on some custom requirement.
9 /// </summary>
10 public class ListBoxStyleSelectors : StyleSelector
11 {
12 public override Style SelectStyle(object item, DependencyObject container)
13 {
14 FrameworkElement frameworkElement = container as FrameworkElement;
15
16 if (frameworkElement != null && item is Contact)
17 {
18 Contact contact = item as Contact; // Contact is the type hosted in each ListBoxItem
19
20 if (contact.Crew == Faction.Strawhat)
21 return (Style)frameworkElement.TryFindResource("SourceListBoxItemStyle1");
22 return (Style)frameworkElement.TryFindResource("SourceListBoxItemStyle2");
23 }
24 return null;
25 }
26 }
27 }
Listing 2: Implementation of a StyleSelector

Unit Testing

I am brand spanking new at this. I only did tests for the Contact model as I was not sure how to test the view models. I used NUnit as my testing framework. Thus far, I did not have to use any stubs or mocks. See Listing 3 for the code.


1 using System.Collections.ObjectModel;
2 using NUnit.Framework;
3 using DragDropUsingMvvmLight01.Model;
4
5 namespace DragDropUsingMvvmLight01.Tests
6 {
7 [TestFixture]
8 public class ContactTests
9 {
10 private Contact _contact = null;
11 private ObservableCollection<Contact> _contacts;
12
13 #region Setup
14 [SetUp]
15 public void Setup()
16 {
17 _contact = new Contact();
18 _contacts = _contact.GetContacts();
19 }
20 #endregion
21
22 [Test]
23 public void GetContacts_ReturnValueIsNotNull_ReturnsTrue()
24 {
25 Assert.That(_contacts, Is.Not.Null);
26 }
27
28 [Test]
29 public void GetContacts_IsTypeofContact_ReturnsTrue()
30 {
31 Assert.That(_contact, Is.InstanceOf<Contact>());
32 }
33
34 [Test]
35 public void GetContacts_HasAtLeastOneItemInCollection_ReturnsTrue()
36 {
37 Assert.That(_contacts.Count, Is.GreaterThanOrEqualTo(1));
38 }
39
40 [Test]
41 public void GetContacts_ObjectIsInGoodState_ReturnsTrue()
42 {
43 var contact = _contacts[0];
44 var firstNamePropertyIsNotNullOrEmpty = contact.Name;
45 var lastNamePropertyIsNotNullOrEmpty = contact.Alias;
46 var phonePropertyIsAValidNumber = contact.Race;
47 var profileImageUrlPropertyIsNotNullOrEmpty = contact.ProfileImageUrl;
48 Assert.That(string.IsNullOrEmpty(firstNamePropertyIsNotNullOrEmpty), Is.False);
49 Assert.That(string.IsNullOrEmpty(lastNamePropertyIsNotNullOrEmpty), Is.False);
50 Assert.That(phonePropertyIsAValidNumber, Is.Not.NaN);
51 Assert.That(string.IsNullOrEmpty(profileImageUrlPropertyIsNotNullOrEmpty), Is.False);
52
53 }
54
55 #region Teardown
56 [TearDown]
57 public void Teardown()
58 {
59 _contact = null;
60 }
61 #endregion
62 }
63 }
64

Listing 3: Unit tests for the Contact model
The code looks mangled here due to a width of 460px and the long names of the test methods.

1 comment:

Robertas Balandis said...

Download link does't work