Thursday, October 1, 2009

Silverlight ComboBoxes and the Importance of Equals

So I was struggling for awhile with a binding issue in my Silverlight application, and learned the hard way that I forgot my basics.

The scenario is fairly common. I have a view model that contains the entity I want to edit along with supporting lists. The common example I see on the web is something like this:

public class CityEntity 
{
   public int ID { get; set; }
   public string Name { get; set; }
}

public class MyEntity 
{
    public CityEntity CurrentCity { get; set; }
}

public class ViewModel 
{
   public MyEntity Entity { get; set; }
   public ObservableCollection<CityEntity> Cities { get; set; }
}

This is purely contrived but you get the point ... I have basic "building block" entities that are composed into the entity I wish to edit, so my view model hosts that entity as well as some collections for binding to drop downs so I can change properties on the entity.

My ComboBox (I thought) was straightforward:

...
<ComboBox Style="{StaticResource SimpleComboBoxStyle}" 
   ItemsSource="{Binding Cities}" 
   SelectedItem="{Binding Path=Entity.CurrentCity,Mode=TwoWay}" DisplayMemberPath="Name"/> 
.. 

Imagine my chagrin when I'd pop up my window and the combo box ... never ... showed ... the city. What was wrong? I had the right path, the right selected item. Was I missing something?

It turns out, I was.

The framework deals with the lists and bindings as objects, so unless the actual reference to the city on the main entity matches the entity in the list, there is no way to "set" the selected item (the framework doesn't know I intend for them to match).

The solution was quite simple: most of my entites on the Silverlight side derive from a base class, call it SimpleEntity. By implementing Equals (and by way of that, the hash code as well), the framework can now understand how to take my entity over here and match it to the entity in the list over there. Once it was implemented, I pushed it out and voila! my combo boxes started populating with the right value.

Jeremy Likness