Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Binding

ComboBox databinding problem solved without Converter

5.00/5 (1 vote)
4 Feb 2012CPOL1 min read 19.4K  
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:

C#
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:

C#
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)