Archive

Author Archive

Refactoring: Extracting the Singleton Pattern

May 4th, 2010 Pedro Sampaio No comments

With this post I will be starting a series of posts on refactoring. The purpose is to use real production code (whenever possible) as a start point and improve it, instead of just random pointless examples.

Starting point

So the main class we will be changing is the DeviceManager. This class manages a collection of Devices (or a dictionary, to be more precise) and allows us to set which is the active device and to get a device by id. Note that this last feature could be handled by the Devices collection, but we are taking advantage of the dictionary to make that look-up more efficient.

One of the key points is that it has a singleton Instance property, that we use throughout the code.

namespace PSampaio.Refactoring.Example1.Old
{
	using System.Collections.Generic;
	using System.Linq;

	public class DeviceManager
	{
		private static DeviceManager deviceManager;
		private static readonly object singletonLock = new object();
		private readonly Dictionary<string, Device> devices;

		public static DeviceManager Instance
		{
			get
			{
				lock (singletonLock)
				{
					if (deviceManager == null)
					{
						deviceManager = new DeviceManager();
					}
					return deviceManager;
				}
			}
		}

		public Device ActiveDevice { get; set; }

		public IEnumerable<Device> Devices
		{
			get { return devices.Values.AsEnumerable(); }
		}

		public DeviceManager()
		{
			devices = new Dictionary<string, Device>();
		}

		public void AddDevice(Device device)
		{
			if (!this.devices.ContainsKey(device.DeviceId))
			{
				this.devices.Add(device.DeviceId, device);
			}
		}

		public bool RemoveDevice(Device device)
		{
			var result = false;
			if (this.devices.ContainsKey(device.DeviceId))
			{
				result = this.devices.Remove(device.DeviceId);
			}
			return result;
		}

		public Device GetDeviceById(string id)
		{
			Device device;
			if (!devices.TryGetValue(id, out device))
			{
				device = null;
			}
			return device;
		}
	}
}

Then we have the actual Device. This class was edited down to the basics, as the real behavior of the Device is not important. For example purposes, it just has an Id that we use to index it in the dictionary.

namespace PSampaio.Refactoring.Example1.Old
{
	public class Device
	{
		public string DeviceId { get; private set ; }

		public Device(string id)
		{
			DeviceId = id;
		}
	}
}

The ActiveDeviceSupport class is the one that uses both the DeviceManager and the Devices. Again, for example purposes, this only sets the first Device we have on the DeviceManager as the ActiveDevice.

namespace PSampaio.Refactoring.Example1.Old
{
	using System.Linq;

	public class ActiveDeviceSupport
	{
		public void SetFirstDeviceAsActive()
		{
			var devices = DeviceManager.Instance.Devices;
			var firstDevice = devices.FirstOrDefault();
			if (firstDevice != null)
			{
				DeviceManager.Instance.ActiveDevice = firstDevice;
			}
		}
	}
}

And finally, we have the set of unit tests run against the DeviceManager. In case you are wondering, yes, these are the actual tests (albeit being slightly edited to protect the innocent) that we have for these classes.

namespace PSampaio.Refactoring.Example1.Old
{
	using System.Collections.Generic;
	using System.Linq;

	using Microsoft.VisualStudio.TestTools.UnitTesting;

	[TestClass]
	public class Tests
	{
		[TestMethod]
		public void AddDevice()
		{
			var devices = new List<Device>();
			for (var i = 1; i < 5; i++)
			{
				var device = new Device(string.Format("Device {0}", i));
				devices.Add(device);
				DeviceManager.Instance.AddDevice(device);
			}
			var thirdDevice = DeviceManager.Instance.GetDeviceById("Device 3");
			Assert.AreSame(devices.First(d => d.DeviceId == "Device 3"), thirdDevice);
		}

		[TestMethod]
		public void ListDevices()
		{
			var devices = DeviceManager.Instance.Devices;
			Assert.AreEqual(4, devices.Count());
		}

		[TestMethod]
		public void RemoveDeviceTest()
		{
			var devices = DeviceManager.Instance.Devices;
			var device = devices.ElementAt(2);
			Assert.IsTrue(DeviceManager.Instance.RemoveDevice(device));
			devices = DeviceManager.Instance.Devices;
			Assert.AreEqual(3, devices.Count());
			Assert.IsFalse(DeviceManager.Instance.RemoveDevice(device));
		}

	}
}

So what’s wrong with the code? The short answer is: a lot!

Fixing the Singleton instance… and removing it

Lets start by analyzing the Singleton instance. The first thing we need to consider when implementing a Singleton instance is whether we really need it, as it’s very likely we don’t. If we do, we should at least implement a double-check lock. See this MSDN page and this Stack Overflow question for more information. Please note that this implementation has to be done just right, so be careful when writing it. I’ve read the block of code below a couple of times, and I think it’s correct, but you never know.

Here’s what we ended up with. Don’t just copy/paste it!

private static volatile DeviceManager instance;
private static readonly object instanceLock = new object();
public static DeviceManager Instance
{
	get
	{
		if (instance == null)
		{
			lock (instanceLock)
			{
				if (instance == null)
				{
					instance = new DeviceManager();
				}
			}
		}

		return instance;
	}
}

In this case, we won’t be needing the Singleton instance so we will just remove this code altogether.

Depend on abstractions

The reason we don’t need the Singleton instance is twofold. First, it limits our ability to test any behavior that uses the DeviceManager (more on this later). Secondly, it forces us to depend on the concrete implementation of the DeviceManager, while what we want is to depend on abstractions. This way, we can promote the cohesiveness of our classes without having a tight coupling between them.

This is better stated in the book Agile Software Development – Principles, Patterns, and Practices by Robert “Uncle Bob” Martin. He calls this the Dependency-Inversion Principle:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.

In order to do this, we need to extract an interface from DeviceManager.

namespace PSampaio.Refactoring.Example1.New
{
	using System.Collections.Generic;
	using System.Linq;

	public interface IDeviceManager
	{
		Device ActiveDevice { get; set; }
		IEnumerable<Device> Devices { get; }
		void AddDevice(Device device);
		bool RemoveDevice(Device device);
		Device GetDeviceById(string id);
	}

	public class DeviceManager : IDeviceManager
	{
		private readonly Dictionary<string, Device> devices;

		public Device ActiveDevice { get; set; }

		public IEnumerable<Device> Devices
		{
			get { return devices.Values.AsEnumerable(); }
		}

		public DeviceManager()
		{
			devices = new Dictionary<string, Device>();
		}

		public void AddDevice(Device device)
		{
			if (!this.devices.ContainsKey(device.DeviceId))
			{
				this.devices.Add(device.DeviceId, device);
			}
		}

		public bool RemoveDevice(Device device)
		{
			var result = false;
			if (this.devices.ContainsKey(device.DeviceId))
			{
				result = this.devices.Remove(device.DeviceId);
			}
			return result;
		}

		public Device GetDeviceById(string id)
		{
			Device device;
			if (!devices.TryGetValue(id, out device))
			{
				device = null;
			}
			return device;
		}
	}
}

We also need to change the ActiveDeviceSupport class. Instead of having a concrete dependency on DeviceManager, we now depend on an abstraction, and that dependency is explicit. We could later evolve this design to use an IOC container to resolve the dependencies automatically.

namespace PSampaio.Refactoring.Example1.New
{
	using System.Linq;

	public class ActiveDeviceSupport
	{
		private readonly IDeviceManager deviceManager;

		public ActiveDeviceSupport(IDeviceManager deviceManager)
		{
			this.deviceManager = deviceManager;
		}

		public void SetFirstDeviceAsActive()
		{
			var devices = deviceManager.Devices;
			var firstDevice = devices.FirstOrDefault();
			if (firstDevice != null)
			{
				deviceManager.ActiveDevice = firstDevice;
			}
		}
	}
}

Correcting the tests

The tests we started with are a perfect example of how not to do unit testing, as they will only pass if they are run all together and in a specific order. While the first (CanAddDevice) test is isolated, the other two depend on the previous ones passing. Obviously, the tests will fail if we run each one separately. The reason for this is that they depend on the Singleton instance of the DeviceManager. So based on the changes we have been making, we can now write the tests differently.

namespace PSampaio.Refactoring.Example1.New
{
	using System.Linq;

	using Microsoft.VisualStudio.TestTools.UnitTesting;

	[TestClass]
	public class Tests
	{
		[TestMethod]
		public void CanAddDevice()
		{
			const string id = "Device 1";
			var deviceManager = new DeviceManager();
			var device = new Device(id);
			deviceManager.AddDevice(device);
			Assert.AreSame(device, deviceManager.GetDeviceById(id));
		}

		[TestMethod]
		public void CanListDevices()
		{
			const int deviceCount = 4;
			var deviceManager = new DeviceManager();
			for (var i = 0; i < deviceCount; i++)
			{
				var device = new Device(string.Format("Device {0}", i));
				deviceManager.AddDevice(device);
			}
			Assert.AreEqual(deviceCount, deviceManager.Devices.Count());
		}

		[TestMethod]
		public void CanRemoveDevice()
		{
			var deviceManager = new DeviceManager();
			var device = new Device("Device 1");
			deviceManager.AddDevice(device);
			Assert.AreEqual(1, deviceManager.Devices.Count());
			deviceManager.RemoveDevice(device);
			Assert.AreEqual(0, deviceManager.Devices.Count());
		}
	}
}

As you can see, each test is now isolated from the others, testing a specific code path in the DeviceManager. There are still changes that we could make, namely the for loop in the ListDevices test and the fact that we call IDeviceManager.AddDevice on the CanRemoveDevice test, but I’m OK with leaving it like that for now.

As a positive side-effect, if we need to test the ActiveDeviceSupport class, we don’t depend on DeviceManager anymore, so we can just mock the IDeviceManager interface and test ActiveDeviceSupport in isolation also.

Hope this helps!

A view model base class to use with MVVM in WPF

July 6th, 2009 Pedro Sampaio 9 comments

As I mentioned in previous posts (here, here, and here), when you develop WPF application, you’ll eventually use view models. So, instead of keep developing them from scratch, I’m posting three different alternatives for easy reference.

The simple view model

public class ViewModelBase : INotifyPropertyChanged
{
	#region Implementation of INotifyPropertyChanged

	public event PropertyChangedEventHandler PropertyChanged;

	protected virtual void OnPropertyChanged(string propertyName)
	{
		OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
	}

	protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
	{
		var handler = PropertyChanged;
		if (handler != null)
			handler(this, args);
	}

	#endregion
}

This is the simplest class you can have. It implements the INotifyPropertyChanged interface and provides two protected methods for you to notify that a specific property as changed. On that takes the string as a parameter, and another that takes a PropertyChangedEventArgs object. The problem with this approach is that you’ll keep creating new instances of PropertyChangedEventArgs, even though you have a limited number of properties in the class.

The smarter view model

public abstract class ViewModelBaseWithArgCache : ViewModelBase
{
	private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;

	protected ViewModelBaseWithArgCache()
	{
		eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
	}

	#region Overrides

	protected override void OnPropertyChanged(string propertyName)
	{
		PropertyChangedEventArgs args;
		if (!eventArgsCache.ContainsKey(propertyName))
		{
			args = new PropertyChangedEventArgs(propertyName);
			eventArgsCache.Add(propertyName, args);
		}
		else
		{
			args = eventArgsCache[propertyName];
		}

		OnPropertyChanged(args);
	}

	#endregion

}

Here, we’re overriding OnPropertyChanged(string propertyName), to provide a custom implementation. First we initialize a dictionary of , that we’re going to use as cache. Now, whenever we call OnPropertyChanged(string property), we check if we have an instance of EventArgs cached for that property. If we do, we return it. If we don’t, we create it, add it to the cache, and then return it. We use that instance to call the protected OnPropertyChanged(PropertyChangedEventArgs args) of ViewModelBase.

The unified view model

public class UnifiedViewModelBase : INotifyPropertyChanged
{
	private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;

	protected UnifiedViewModelBase()
	{
		eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
	}

	#region Implementation of INotifyPropertyChanged

	public event PropertyChangedEventHandler PropertyChanged;

	protected void OnPropertyChanged(string propertyName)
	{
		PropertyChangedEventArgs args;
		if (!eventArgsCache.TryGetValue(propertyName, out args))
		{
			args = new PropertyChangedEventArgs(propertyName);
			eventArgsCache.Add(propertyName, args);
		}

		OnPropertyChanged(args);
	}

	protected void OnPropertyChanged(PropertyChangedEventArgs args)
	{
		var handler = PropertyChanged;
		if (handler != null)
			handler(this, args);
	}

	#endregion
}

Now, instead of have a two-level hierarchy of classes, we combined them together in a single UnifiedViewModelBase. You may want to rename this class to something like ViewModelBase.

You can download all the code in this post by clicking this link.

Hope this helps!

Shout it

kick it on DotNetKicks.com

Categories: Development Tags: , ,

Using Data Binding with Static Resources in WPF

June 16th, 2009 Pedro Sampaio 2 comments

If you’ve been using WPF for more than a couple of weeks, I’m sure you wrote code like this a lot of times: you define a resource and reference it with StaticResource.

<Window x:Class="PSampaio.StaticResourcesWithBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Width="400" Height="200">
	<Window.Resources>
		<SolidColorBrush x:Key="RedBrush" Color="#FFFF0000" />
	</Window.Resources>
	<Grid>
		<TextBlock Text="Hello World" FontSize="48" Foreground="{StaticResource RedBrush}" />
	</Grid>
</Window>

However, if you applications are getting increasingly more complex, then it can start to get more tricky. In this post, I’ll be showing how to use resources for which you don’t know in design time the key to use in xaml (maybe because you’re loading them dynamically), by binding them to view model properties (which, by the way, you should be using).

Setting the scene

Suppose you’re indeed loading the resources dynamically, like so:

<Application x:Class="PSampaio.StaticResourcesWithBinding.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
	<Application.Resources>
		<SolidColorBrush x:Key="RedBrush" Color="#FFFF0000" />
	</Application.Resources>
</Application>

Yes, yes, I know. You can reference that resource the usual way, but this is just sample code, so assume you can’t. We’re also using a view model that contains a property with the key for the resource you want to use (that maybe you got that after loading the resource dynamically). That model is being instanced from the window constructor. Again, let me stress that this is sample code that you need to adapt to fit your own circumstances.

public Window1()
{
	InitializeComponent();

	DataContext = new MyViewModel("RedBrush");
}
namespace PSampaio.StaticResourcesWithBinding
{
	public class MyViewModel
	{
		public string MyResourceKey { get; private set; }

		public MyViewModel(string myResourceKey)
		{
			MyResourceKey = myResourceKey;
		}
	}
}

Are you with me so far? Good. Lets move on!

The obvious solution

Your first reaction to this will be to actually use the binding in a StaticResource. You can go ahead and try it if you want to. You’ve get to something like this:

<Window x:Class="PSampaio.StaticResourcesWithBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Width="400" Height="200">
	<Grid>
		<TextBlock Text="Hello World" FontSize="48" Foreground="{StaticResource {Binding MyResourceKey}}" />
	</Grid>
</Window>

This code will compile just fine, but if you run it, you’ll get an exception. This is because the StaticResource key is only evaluated when it’s needed, and when it tries to provide a value, it can’t find a resource named ‘{System.Windows.Data.Binding}’. So we’ll have to find another way, since this clearly won’t work.

A better solution

The only place were we can make this work is the markup itself, so lets start from the top, with the syntax we want to use, and go from there all the way to the bottom. We want this to work:

<Window x:Class="PSampaio.StaticResourcesWithBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Width="400" Height="200">
	<Grid>
		<TextBlock Text="Hello World" FontSize="48" Foreground="{BindableStaticResource {Binding MyResourceKey}}" />
	</Grid>
</Window>

In order for this to work, we need to create a new markup extension, so lets do just that. Create a new class that derives from the original StaticResourceExtension, called BindableStaticResourceExtension. Notice that the suffix is optional in XAML, and that you’ll need to add the namespace prefix in the markup. Create it with 2 constructors, one empty, and one with the Binding. You should have this class for now.

using System.Windows;
using System.Windows.Data;

namespace PSampaio.StaticResourcesWithBinding
{
	public class BindableStaticResource : StaticResourceExtension
	{
		public Binding Binding { get; set; }

		public BindableStaticResource()
		{
		}

		public BindableStaticResource(Binding binding)
		{
			Binding = binding;
		}
	}
}

Now the tricky part, when and how do you get the actual resource key, and what exactly do you do with it. The ‘when’ part is the easy one: there’s one method you can override public override object ProvideValue(IServiceProvider serviceProvider) that the framework will call in order to get the value. In this method, you have to evaluate the binding and get its result (the ‘how’) and set it to the ResourceKey in the base StaticResourceExtension class (the ‘what to do’). After that, you can delegate the rest of the work to the base class and let it provide it’s value. I’ll first show the code, and then go through it.

private static readonly DependencyProperty DummyProperty;

static BindableStaticResource()
{
	DummyProperty = DependencyProperty.RegisterAttached("Dummy",
										     typeof (Object),
										     typeof (DependencyObject),
										     new UIPropertyMetadata(null));
}

public override object ProvideValue(IServiceProvider serviceProvider)
{
	var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
	var targetObject = (FrameworkElement)target.TargetObject;

	MyBinding.Source = targetObject.DataContext;
	var DummyDO = new DependencyObject();
	BindingOperations.SetBinding(DummyDO, DummyProperty, MyBinding);

	ResourceKey = DummyDO.GetValue(DummyProperty);

	return base.ProvideValue(serviceProvider);
}

It may take a little to fully understand what’s going on here, but it’s fairly easy (once you figure it out). You need to query the service provider for an IProvideValueTarget. The returned object has two properties: TargetObject and TargetProperty. This tells you which property of which object we’re evaluating the binding for. You set the source of the binding to the data context of the target object, meaning “look here for the path you want”. This is the only use you’ll have for the target object

You then set the binding on a dummy DependencyObject, with a dummy property. If you use TargetProperty here, the binding operation will try to convert the resulting value to the type of the property. In this case, it would try to convert the string “RedBrush” to an actual Brush object, as that’s the type of TargetProperty (Foreground is a Brush). After this, all you need to do is get the value from the dummy property.

Now that ResourceKey contains the resource key we need, just call base.ProvideValue(serviceProvider) and let StaticResourceExtension try and find a resource with that key. Hope this helps!

You can download the code from this link.

Shout it kick it on DotNetKicks.com

An Introduction to ObservableCollection in WPF

April 28th, 2009 Pedro Sampaio 5 comments

The ObservableCollection<T> is one of the most important features of WPF data binding. From the documentation:

Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.

Most people seem confused about this, so it’s worth a clear note. An ObservableCollection is just like a regular collection. If you check the documentation, you can see that ObservableCollection is defined as:

public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged

So you have access to all the members you would have in Collection<T>. Again, refer to the documentation for the list of all those members.

Notice that, like any collection that derives from Collection<T>, its methods (namelly Add and Remove) accept null parameters and do not throw an exception.

But the main feature of the ObservableCollection<T> are the events it raises when the items it contains change. By implementing the INotifyCollectionChanged and INotifyPropertyChanged interfaces, the collection has events for CollectionChanged and PropertyChanged. All these events are related. The first one is raised whenever something changed in the collection, be it Add, Remove, Move, etc. This also trigger the PropertyChanged event for the Items[] property. When you’re adding or removing items, PropertyChanged is also raised for the Count property.

But enough theory, here’s a small example of how to use it. First of all, we start with our domain model, the Person.

namespace PSampaio.ObservableCollectionSample
{
	public class Person
	{
		public string FirstName { get; set; }
		public string LastName { get; set; }
		public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } }
	}
}

Next, we have a ViewModel that uses this domain model.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace PSampaio.ObservableCollectionSample
{
	public class PickOneViewModel
	{
		readonly Random random = new Random();

		public List<Person> AvailablePeople { get; private set; }
		public ICommand PickOnecommand { get; private set; }
		public ObservableCollection<Person> SelectedPeople { get; private set; }

		public PickOneViewModel()
		{
			AvailablePeople = new List<Person>
			{
				new Person {FirstName = "John", LastName = "Doe"},
				new Person {FirstName = "Michael", LastName = "Jones"},
				new Person {FirstName = "Jane", LastName = "Smith"},
			};

			PickOnecommand = new DelegateCommand<object>(obj =>
			{
				int availablePersonIndex = random.Next(0, AvailablePeople.Count);
				SelectedPeople.Add(AvailablePeople[availablePersonIndex]);
			});

			SelectedPeople = new ObservableCollection<Person>();
		}
	}
}

This PickOneViewModel has three properties, that we will bind to in the Window XAML. AvailablePeople is just a list of the people available to be selected. It’s just a standard List because we do not want to update it, just use it as a source for SelectedPeople. PickOneCommand is a DelegateCommand. This delegate command was based on the CompositeWPF class with the same name, and lets the you create an ICommand that’s defined with delegates, instead of CommandBindings. Finally, SelectedPeople is an ObservableCollection that starts empty and where we will be adding the (random) person selected each time we execute PickOneCommand.

The UI for this sample is fairly simple. Just add the ViewModel as an ObjectDataProvider to the window resources and use it as a DataSource for the window contents.

<Window
	x:Class="PSampaio.ObservableCollectionSample.Window1"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:Sample="clr-namespace:PSampaio.ObservableCollectionSample"
	Title="Window1"
	Width="300"
	Height="300">

	<Window.Resources>
		<ObjectDataProvider
			x:Key="Viewmodel"
			ObjectType="{x:Type Sample:PickOneViewModel}"/>
	</Window.Resources>

	<DockPanel DataContext="{StaticResource Viewmodel}">
		<ListView DockPanel.Dock="Left" Width="130"
			ItemsSource="{Binding AvailablePeople}"
			DisplayMemberPath="FullName" />
		<ListView DockPanel.Dock="Right" Width="130"
			ItemsSource="{Binding SelectedPeople}"
			DisplayMemberPath="FullName" />
		<Button Width="20"
			Command="{Binding PickOnecommand}"
			Content=">>"/>
	</DockPanel>
</Window>

It really is that simple. What is happening is that, when you click on the button, PickOneCommand is executed, adding one random person to the SelectedPerson collection. When that occurs, the list raises a CollectionChanged event that WPF listens. By now, the data binding knows that, because the list has changed, that it needs to update its contents, which it does.

So now you know how to use ObservableCollection. Please keep in mind that you don’t have use a view model, although I would consider it a best practice, that allows you to effectively separate the content from the presentation. Also, you can replace DelegateCommand with your CommandBindings if you prefer. Again, this is a matter of preference, as I believe using it makes for cleaner code.

kick it on DotNetKicks.com

Categories: Development Tags: ,

Creating a Custom Observable Collection in WPF

April 13th, 2009 Pedro Sampaio 8 comments

One of the biggest advantages WPF has is its Data Binding features. Data Binding can be done in several ways, but the most common is using the INotifyPropertyChanged and INotifyCollectionChanged interfaces. For simple objects, all you need to do is implement the INotifyPropertyChanged, and raise the PropertyChanged event when your properties change. Maybe something like this:

public class MySampleClass : INotifyPropertyChanged
{
    public int MyProperty
    {
        get
        {
            return _myProperty;
        }
        set
        {
            if (_myProperty == value)
                return;

            _myProperty = value;
            OnPropertyChanged("MyProperty");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Instead of having each class implement the interface, you can create a base class that already does that, and inherit from this new one. You can see an example on this post. However, remember that you can only inherit from one class, so make sure you structure you class hierarchy properly. My advice is to use this only in presentation objects (or view models, if you’re using MVVM)

When you want to bind to a collection, you will want to use ObservableCollection<T>. This collection implements both interfaces, therefore notifying you when the items in the collection change and when the items’ properties change. This works great if you’re using standard collections. The problem arises when you want to use a custom collection. When you create an ObservableCollection<T> on v3.5, you have 3 constructors that rely on Collection<T> to create a new list. If you pass a List<T> or IEnumerable<T>, all that it does is copy the items, between both collections. This will of course make you custom collection useless. For this to work, you will have to create a new “Observable” wrapper around your custom collection. Lets start with the interface. All we need is a collection that implements the two interfaces we discussed earlier.

public interface ICustomObservableCollection<T> : ICollection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
}

Before we move on the the implementation, first we need to better understand what is it that we’re trying to do and how to achieve it. We have a custom collection that we need to add additional features, so we need to “decorate” our collection with new behavior. For this we can follow the Decorator Pattern.

public class CustomObservableCollection<T> : ICustomObservableCollection<T>
{
    #region Fields
    ...
    #endregion

    #region Properties
    protected ICollection<T> InnerCollection { get; private set; }
    #endregion

    #region Constructors

    public CustomObservableCollection(ICollection<T> innerCollection)
    {
        if (innerCollection == null)
            throw new ArgumentNullException("innerCollection");

        InnerCollection = innerCollection;
    }

    #endregion

    #region Implementation

    #region Implementation of INotifyCollectionChanged
    ...
    #endregion

    #region Implementation of INotifyPropertyChanged
    ...
    #endregion

    #region Implementation of IEnumerable
    ...
    #endregion

    #region Implementation of ICollection<T>
    ...
    #endregion

    #endregion
}

Now that we have both collections wrapped on inside the other, all we need to do is provide the implementation of the interfaces. Starting with INotifyPropertyChanged:

#region Implementation of INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, e);
    }
}

private void OnPropertyChanged(string propertyName)
{
    OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}

#endregion

Then, we can implement INotifyCollectionChanged. For this implementation to work correctly, we need to add a monitor, so that we detect collection reentrancy. We can do this with this SimpleMonitor class, that implements IDisposable, and just keeps a counter of entries. We also need to provide methods tor activating the monitor.

#region SimpleMonitor
protected IDisposable BlockReentrancy()
{
    this._monitor.Enter();
    return this._monitor;
}

protected void CheckReentrancy()
{
    if ((this._monitor.Busy && (CollectionChanged != null)) && (CollectionChanged.GetInvocationList().Length > 1))
    {
        throw new InvalidOperationException("Collection Reentrancy Not Allowed");
    }
}

[Serializable]
private class SimpleMonitor : IDisposable
{
    private int _busyCount;

    public bool Busy
    {
        get { return this._busyCount > 0; }
    }

    public void Enter()
    {
        this._busyCount++;
    }

    #region Implementation of IDisposable

    public void Dispose()
    {
        this._busyCount--;
    }

    #endregion
}
#endregion

This SimpleMonitor is created in the CustomObservableCollection constructor, so we need to account for that too.

#region Fields
private readonly SimpleMonitor _monitor;
#endregion

#region Constructors

public CustomObservableCollection(ICollection innerCollection)
{
    this._monitor = new SimpleMonitor();

    if (innerCollection == null)
    {
        throw new ArgumentNullException("innerCollection");
    }

    InnerCollection = innerCollection;
}

#endregion

Now, we’re ready to provide an implementation for INotifyCollectionChanged.

#region Implementation of INotifyCollectionChanged

public event NotifyCollectionChangedEventHandler CollectionChanged;

protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    if (CollectionChanged != null)
    {
        using (BlockReentrancy())
        {
            CollectionChanged(this, e);
        }
    }
}

private void OnCollectionChanged(NotifyCollectionChangedAction action, object item)
{
    OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item));
}

private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
{
    OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
}

private void OnCollectionReset()
{
    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

#endregion

The next one is IEnumerable. For this one, we will delegate to the InnerCollection.

#region Implementation of IEnumerable

public IEnumerator GetEnumerator()
{
    return InnerCollection.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

#endregion

Finally, provide the implementation for ICollection<T>. Again, this will delegate to the InnerCollection raising events when needed. Notice the use of the CountString and IndexerName fields.

#region Fields

private const string CountString = "Count";
private const string IndexerName = "Item[]";

private readonly SimpleMonitor _monitor;

#endregion
#region Implementation of ICollection

public void Add(T item)
{
    CheckReentrancy();
    InnerCollection.Add(item);
    OnPropertyChanged(CountString);
    OnPropertyChanged(IndexerName);
    OnCollectionChanged(NotifyCollectionChangedAction.Add, item, InnerCollection.Count);
}

public void Clear()
{
    CheckReentrancy();
    InnerCollection.Clear();
    OnPropertyChanged(CountString);
    OnPropertyChanged(IndexerName);
    OnCollectionReset();
}

public bool Contains(T item)
{
    return InnerCollection.Contains(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
    InnerCollection.CopyTo(array, arrayIndex);
}

public bool Remove(T item)
{
    CheckReentrancy();
    bool result = InnerCollection.Remove(item);
    OnPropertyChanged(CountString);
    OnPropertyChanged(IndexerName);
    OnCollectionChanged(NotifyCollectionChangedAction.Remove, item);
    return result;
}

public int Count
{
    get { return InnerCollection.Count; }
}

public bool IsReadOnly
{
    get { return InnerCollection.IsReadOnly; }
}

#endregion

You can download the source code here.

Update: Added the source code as a compressed file. You can get it here.

kick it on DotNetKicks.com

No clues, just money

February 23rd, 2009 Pedro Sampaio No comments

Please remove your card

I’m not the kind of person to carry much money in my wallet. I usually depend on debit or credit cards for most of my transactions. But while this is much more convenient for me, it sometimes is a nuisance, like the one that happened just a couple of days ago.

ATMI was having dinner at a local restaurant, and when we finished the meal, we proceeded to pay with the debit card. The waitress keys in the value, “Please press OK, then your code, and then OK once again. And so I did: ” OK … #### … OK”. After a couple of minutes later, the answer comes: “Please remove your card”. No receipt, no error message, nothing. Just “Please remove your card”. Figuring there was something wrong with the communication, we tried again. “OK … #### … OK”.  And again, the result was the same: “Please remove your card”.

Without any other clues to what was going on, we decided that the card was the culprit, and tried another time with a different card from a different bank. This time, it was even worse, as there was no message displayed, not even asking to remove the card.

No paper, what else?

After all these unsuccessful attempts, the waitress called another waitress that was passing by and asked her if she could help. She thought of the obvious (it’s always obvious looking back): “Have you checked if the machine has paper?” Well, of course it didn’t. Just as soon as she opened the machine, we all noticed the empty cardboard roll. Now, it’s true that the waitress that used it the last time when the paper ended could have changed it, but this is clearly an User Experience problem.

The main issue here is that the portable payment terminal gives insufficient information regarding this error (and eventually even gives no information at all). This could be corrected with a simple message stating the actual problem: “Unable to print receipt. No paper.” This would be enough for someone using the machine to at least understand what’s going on.

But we could go even further. When you’re starting a transaction, the machine could preemptively warn the user that it’s not possible to proceed with it. At the very least, if the user is still allowed to carry on with the transaction, keep him informed about what will happen: “Unable to print receipt. Do you want to continue with the transaction?” This way, the user is able to make an informed decision.

Finally, how hard would it be to include a small blinking light, signaling that there is not paper?

Bottom line

Sometimes we don’t really think about the objects that surrounds us, and how they impact our lives every day. It takes a lot of time to get the interaction with these objects just right, and with a little effort, we can actually make them enjoyable. This is the purpose of User Experience.

Oh, and I did get charged 3 times, so I had to go to an ATM, get the last transactions in my accounts and take it back to the restaurant so they could refund me.

Categories: User Experience Tags: , ,

Lets get the ball rolling

February 3rd, 2009 Pedro Sampaio No comments

Hi. My name is Pedro Sampaio and I work for FARO Technologies, in the SWE-UX team based in Oporto, Portugal. I’m just finishing setting up this blog and hopefully will start posting more regularly soon.

Hope you all find my posts helpful and I look forward to some great interactions!

Categories: Misc Tags: