WPF: How to set the SelectedValue on Data Bound ComboBox

Most of the time when you have a form, you will have some combo boxes, and some list boxes. If you are editing an existing item, most likely you are going to want to have these items display the currently selected value. So we are going to populate a form with some contacts and provide a combo box of companies that they could work for. When we select an individual contact from our list, we would expect the combo box to change and show the company the contact currently is associated with.

We want to start by creating a couple of objects, 1 for company details and another for our contacts. So start out be creating a new class and you can call it Company.

Company.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;namespace MyContacts
{
public class Company : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void Notify(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} int pId;
public int Id
{
get { return pId; }
set
{
if (pId == value)
return;
pId = value;
Notify(“Id”);
}
} string pName;
public string Name
{
get { return pName; }
set
{
if (pName == value)
return;
pName = value;
Notify(“Name”);
}
}

public Company(int id, string name)
{
Id = id;
Name = name;
}
}

public class Companies : ObservableCollection { }

public class CompanyKeeper
{
public Companies LoadCompanies()
{
Companies companies = new Companies();
companies.Add(new Company(1, “Microsoft”));
companies.Add(new Company(2, “Symantec”));
companies.Add(new Company(3, “Oracle”));
companies.Add(new Company(4, “Apple”));
return companies;
}
}
}

We also need a 2nd class for the Contacts.

Contact.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;namespace MyContacts
{
public class Company : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void Notify(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} int pId;
public int Id
{
get { return pId; }
set
{
if (pId == value)
return;
pId = value;
Notify(“Id”);
}
} int pCompanyId;
public int CompanyId
{
get { return pCompanyId; }
set
{
if (pCompanyId == value)
return;
pCompanyId = value;
Notify(“CompanyId”);
}
}

string pFirstName;
public string FirstName
{
get { return pFirstName; }
set
{
if (pFirstName == value)
return;
pFirstName = value;
Notify(“FirstName”);
}
}

string pLastName;
public string LastName
{
get { return pLastName; }
set
{
if (pLastName == value)
return;
pLastName = value;
Notify(“LastName”);
}
}

public Contact(int id, int companyId, string firstName, string lastName)
{
Id = id;
CompanyId = companyId;
FirstName = firstName;
LastName = lastName;
}
}

public class Contacts : ObservableCollection<Contact> { }

public class ContactKeeper
{
public Contacts LoadContacts()
{
Contacts contacts = new Contacts();
contacts.Add(new Contact(1, 1, “Bill”, “Gates”));
contacts.Add(new Contact(2, 1, “Steve”, “Ballmer”));
contacts.Add(new Contact(3, 2, “John”, “Thompson”));
contacts.Add(new Contact(4, 3, “Lawrence”, “Ellison”));
contacts.Add(new Contact(5, 4, “Steve”, “Jobs”));
return contacts;
}
}
}

The SelectedValuePath is the Property from the Company object and the SelectedValue is the Id in the Contact object. Remember we called ours CompanyId. The 2 key items that you need to be sure to set in order to have the combobox display the currently selected company when you select a contact is to set

  • SelectedValuePath – This is the Property from the ItemsSource. In our case of using the Company object, it is the Id field.
  • SelectedValue – This is the CompanyId Property from our Contact object.

Windows1.xaml

<Window x:Class=”MyContacts.Window1″
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
xmlns:local=”clr-namespace:MyContacts”
Title=”Window1″ Width=”300″ Height=”275″>

<Window.Resources>
<ObjectDataProvider
x:Key=”Contacts”
IsAsynchronous=”True”
ObjectType=”{x:Type local:ContactKeeper}”
MethodName=”LoadContacts”/>

<ObjectDataProvider
x:Key=”Companies”
ObjectType=”{x:Type local:CompanyKeeper}”
MethodName=”LoadCompanies”/> <DataTemplate DataType=”{x:Type local:Contact}”>
<TextBlock>
<TextBlock Text=”{Binding Path=LastName}” />
, <TextBlock Text=”{Binding Path=FirstName}”/>
</TextBlock>
</DataTemplate>

<DataTemplate x:Key=”CompanyDataTemplate”>
<TextBlock>
<TextBlock Text=”{Binding Path=Name}” />
</TextBlock>
</DataTemplate>
</Window.Resources>

<Grid DataContext=”{StaticResource Contacts}” Height=”Auto”>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”100″/>
<ColumnDefinition/>
</Grid.ColumnDefinitions> <ListBox Grid.ColumnSpan=”2″ ItemsSource=”{Binding}” IsSynchronizedWithCurrentItem=”True” Margin=”5″/>

<!– First Name –>
<Label Content=”First Name:” Grid.Row=”1″ Margin=”5″/>
<TextBox Text=”{Binding Path=FirstName}” Grid.Row=”1″ Grid.Column=”1″ Margin=”5″/>

<!– Last Name –>
<Label Content=”Last Name:” Grid.Row=”2″ Margin=”5″/>
<TextBox Text=”{Binding Path=LastName}” Grid.Row=”2″ Grid.Column=”1″ Margin=”5″/>

<!– Company –>
<Label Content=”Company:” Grid.Row=”3″ Margin=”5″/>
<ComboBox x:Name=”companyComboBox” IsSynchronizedWithCurrentItem=”True” Margin=”5″
Grid.Row=”3″ Grid.Column=”1″ SelectedValuePath=”Id” SelectedValue=”{Binding Path=CompanyId}”
ItemsSource=”{Binding Source={StaticResource Companies}}” ItemTemplate=”{StaticResource CompanyDataTemplate}” />
</Grid>
</Window>

1 comment so far

  1. ed on

    good topic!

    Actually, you dont need to inherit INotifyPropertyChanged for both classes Contact and Company since ObservableCollection already provides notifications.

    From msdn
    http://msdn.microsoft.com/en-us/library/ms668604.aspx

    ObservableCollection(T) Class definition:
    “Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.”

    I took the example, got rid of the notifying setters and it works find!

    Contact would be:
    public class Contact
    {
    public int Id { get; set; }

    public int CompanyId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public Contact(int id,
    int companyId,
    string firstName,
    string lastName)
    {
    this.Id = id;
    this.CompanyId = companyId;
    this.FirstName = firstName;
    this.LastName = lastName;
    }
    }


Leave a reply