Setting two bindings on a single WPF control






4.47/5 (7 votes)
This article demonstrates how to set two bindings on a WPF control, yielding significant amount of code reduction for developers & boosting their productivity.
Introduction
One of the major motivations to move to WPF is to leverage on its Binding framework. This article assumes that you are already comfortable with this wonderful piece of technology. In here, I will try addressing a common issue which might look unusual at first. I will start with a scenario on which we will be building during the course of the article. I have kept things simple, so that the underlying message is clear, but the same solution can be applied to more complex scenarios yielding significant code reduction & easy maintenance.
Background
Assume you have a patient screen which displays details about a given patient. On this Screen you have a ComboBox which displays various blood groups. Default selected blood group in the ComboBox should come from the current patient that is being displayed on the screen. Also whenever selection changes in combo box it should change the displayed patient’s blood group as well.

Building the Code
To start with we want to display a bunch of items inside a WPF control in this case a ComboBox. These items would typically reside in a master table inside a Database. To get this up & running you have to set the local data context for the ComboBox along with its ItemsSource property. Let’s see some code to put things in perspective. Below is our class BloodGroup (you can assume a similar corresponding table inside the Database).
public class BloodGroup : INotifyPropertyChanged
{
private int _code;
private string _name;
public int Code
{
get { return _code; }
set
{
_code = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Code"));
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Consider the XAML and code below to display a list of blood groups inside a ComboBox. Ideally you would fetch this data from a Database but for simplicity I am going to build an in memory collection.
<StackPanel> <ComboBox x:Name="cbBloodGroups" ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValuePath="Code" /> </StackPanel>
public Window1()
{
InitializeComponent();
ObservableCollection<BloodGroup> bloodGroups =
new ObservableCollection<BloodGroup>() {
//Fill the collection; this could have been done via
//objects retrived from a WCF Service
new BloodGroup() {Code = 1, Name = "O+ve"},
new BloodGroup() {Code = 2, Name = "O-ve"},
};
cbBloodGroups.DataContext = bloodGroups;
}
Fine, so this is simple stuff. Now starts the real problem. Let’s say that we have a Patient class with a single property called BloodGroupCode as follows:
public class Patient: INotifyPropertyChanged
{
private int _bloodGroupCode;
public int BloodGroupCode
{
get { return _bloodGroupCode; }
set
{
_bloodGroupCode = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("BloodGroupCode"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
ComboBox’s current item of display should be decided by the BloodGroupCode property of Patient’s class. How can we set that? We can’t remove ItemsSource Binding on the combo box or replace it as that is providing items. So we need to add one more binding to the combo box. Let’s see how.
Solution
Patient object ideally would be a row in some Database table, to which we would get access only at run time. Hence we can create an ObjectProvider in the resource collection of the window & initialize its ObjectInstance property to null. At run time when we retrieve the actual object from Database we can do the assignment. Once done with adding ObjectProvider, we can access the patient object via StaticResource markup extension in the ComboBox and set the ComboBox’s SelectedValue property. This works like a charm for the issue we are trying to address. Steps are as below:
First Step
Define an Object Provider in Resource collection of your Window / Page / UserControl & set SelectedValue Property for the combo box by using StaticResource extension with corresponding Path value.<Window.Resources> <ObjectDataProvider x:Key="dataProvider" ObjectInstance="{x:Null}" /> </Window.Resources> <StackPanel> <ComboBox … SelectedValue="{Binding Source={StaticResource dataProvider}, Path=BloodGroupCode}" /> </StackPanel>
Second Step:
Next step is to set ObjectInstance which was originally initialized to Null.
public Window1()
{
InitializeComponent();
… // Binding the Combo Box with items as before
var dataProvider = this.Resources["dataProvider"] as ObjectDataProvider;
if (dataProvider != null)
dataProvider.ObjectInstance = new Patient() {BloodGroupCode = 2};
//The above assignment could be object retrived via WCF Service
}
That’s it. With Patient Object implementing INotifyPropertyChanged interface the binding is bidirectional. When you modify the Patient Object the ComboBox selection changes, & when you change the selection in ComboBox the underlying Patient object’s BloodGroupCode property changes. Hence you have two bindings set on a combo box & both work as expected.