ComboBox databinding problem solved without Converter





5.00/5 (1 vote)
It is not necessary to create a converter to bind a ComboBox to an object
Most recommendations for binding complex objects in Silverlight involve converters. This works great, but I find creating another class and keeping track of it to be a nuisance.
To understand the problem, consider an
ObservableCollection<customer>
where the Customer
has a CustomerType
object that we want to handle in a ComboBox
. The Customer
class looks like:
public class Customer
{
public int ID { get;set;}
public string Name { get;set;}
public CustomerType Type { get;set;}
}
public class CustomerType
{
public int ID { get;set;}
public string Name { get;set;}
}
Now, if I send a list of Customers
to a DataGrid
in Silverlight (I am using a DomainDataSource
, but it doesn't matter), I will not succeed with something like this:
<sdk:DataGridTemplateColumn x:Name="customerType" Header="Type"> (sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Data, ElementName=customerDomainDataSource}" SelectedValue="{Binding Path=Type, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn>Since
DomainDataSource
produces a partial class for Customer
, just as does WCF, I add this extension to my CustomerClass
:
public partial class Customer
{
public static ObservableCollection<customertype> Types { get;set;}
public int CustomerTypeID
{
get
{
return Type.ID;
}
set
{
// using Linq to get the matching item from the list
Type = Types.FirstOrDefault(t => t.ID == value);
}
}
}
Notice that we have to have the Types available somehow. I simply grab the list from the ComboBox.ItemsSource
when it becomes available (asynchronous, remember) and put it into my Customer.Types
list (static
so I don't have to do it for every Customer
).
Now, I change the line above to:
SelectedValue="{Binding Path=CustomerTypeID, Mode=TwoWay}"Now, my
ComboBox
works perfectly.
By the way, the reason that the alternate approach doesn't work is not immediately obvious, but it is caused by the fact that the object comparison of the CustomerType
list in the combo with the Customer.Type
because they are not the same object. They have the same ID, but we have to force them to compare by ID.
I prefer this because it is immediately obvious where the conversion is taking place, and I don't have to track yet another class that I forget to use the next time I need a CustomerType listbox
or combobox
.