Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Binding to ComboBox.SelectedItem through a custom dependency property

0.00/5 (No votes)
21 Oct 2009 1  
Today we are looking into databinding to the ComboBox.SelectedItem property through a custom dependency property in a UserControl.

Today we are looking into databinding to the ComboBox.SelectedItem property through a custom dependency property in a UserControl.

Post 42

But before all that I want to let you all know, this is post #42 on Developers 42. For obvious reasons, this is a special post on my blog. As I started out last year, I didn't have any visitors, but now I average about 1700 visits a month. A large part of these visits come through Google, but a special thanks goes out to Dave Campbell for publishing a lot of my articles on SilverlightCream.com. Through his great efforts of bringing us the latest and greatest on Silverlight, his website is the second greatest referrer, only topped by Google. I won't elaborate any more on this. Stats, highs and lows will all be published in October when the blog celebrates it's first year of existence.

Binding to ComboBox.SelectedItem through a custom dependency property in a UserControl, I ran into this building a user control based on the requirement that we need a combo box that includes an edit button next to it when needed and also provides a label when needed. The simplest way to do this (at least as I see it), is through building two UserControls. The first combines the ComboBox with a Button and the second combines the result with a TextBlock. Today we want to focus on the first one, which I dubbed ExtendedComboBox. I wrote the following XAML as a start:

XML
<UserControl
xmlns:input="clr-namespace:System.Windows.Controls;
	assembly=System.Windows.Controls.Input"
xmlns:inputToolkit="clr-namespace:System.Windows.Controls;
	assembly=System.Windows.Controls.Input.Toolkit"
x:Class="ExtendedComboBox.ExtendedComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
x:Name="extendedComboBoxControl"
>
<StackPanel x:Name="stackPanel" Orientation="Horizontal" HorizontalAlignment="Stretch">
<ComboBox x:Name="comboBox"
HorizontalAlignment="Stretch"
SelectionChanged="comboBox_SelectionChanged"
>
</ComboBox>
<Button x:Name="editButton" Content="..." Padding="5,0,5,0"
    LayoutUpdated="editButton_LayoutUpdated"
Click="editButton_Click"/>
</StackPanel>
</UserControl>

Simple enough. All I had to do now was add some dependency properties to control some functionality and Bob's your uncle, right? Wrong! I will spare you the details on sizing specifics and events, as this is not the focus of this article.

For databinding, I figured I would need to bind to the ItemsSource and the SelectedItem properties of the ComboBox. Here is the code I initially came up with:

C#
publicIEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set
{
SetValue(ItemsSourceProperty, value);
comboBox.ItemsSource = value;
}
}

// Using a DependencyProperty as the backing store for ItemsSource.
// This enables animation, styling, binding, etc...
publicstaticreadonlyDependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
    typeof(ExtendedComboBox), newPropertyMetadata(null));

publicobject SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set
{
SetValue(SelectedItemProperty, value);
comboBox.SelectedItem = SelectedItem;
}
}

// Using a DependencyProperty as the backing store for SelectedItem.
// This enables animation, styling, binding, etc...
publicstaticreadonlyDependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(ExtendedComboBox),
    newPropertyMetadata(null));

As you can see, these are standard dependency properties, only I've added a line to assign their values through to the ComboBox. For the ItemsSource property this works like a charm, however, for the SelectedItem property it doesn't.

After struggling with this, building a complete test rig and reading through books worth of blog posts, I finally came up with the following solution. I removed the passing through of the value in the properties setter method and added manual binding for the property in the constructor of the ExtendedCombobox. Here is my new constructor:

C#
public ExtendedComboBox()
{
InitializeComponent();
Binding selectedItemBinding = newBinding("SelectedItem");
selectedItemBinding.Source = this;
selectedItemBinding.Mode = BindingMode.TwoWay;
comboBox.SetBinding(ComboBox.SelectedItemProperty, selectedItemBinding);
}

This way the ExtendedComboBox becomes the source of the binding for the ComboBox.SelectedItem property. After adding this (and obviously also implementing the Equals and GetHashCode methods on the business objects involved), it now works like a charm, without having to write any extra code in the modules that use this control.

Please leave me a comment if you have any questions, remarks or if you just want to say hi.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here