How to: Use the Master-Detail Pattern with WPF Hierarchical DataTemplate






4.88/5 (24 votes)
This article shows a simple way to implement Master-Detail pattern with hierarchical DataTemplate
- Download Hierarchical_MasterDetail_Simple-noexe.zip - 26.6 KB
- Download Hierarchical_MasterDetail_Simple.zip - 61.5 KB
- Download Hierarchical_MasterDetail_Advanced-noexe.zip - 1.4 MB
- Download Hierarchical_MasterDetail_Advanced.zip - 2.8 MB

Introduction
This article shows a practical & simple way to implement Master-Detail pattern with hierarchical DataTemplate.
Background
Master-Detail is a frequently used pattern in computer science and information systems. Almost every data oriented project is using this pattern. The principle is very simple, showing list of details by selected master item:
We can implement Master-Detail in multiple ways to achieve this pattern, in my opinion the easiest way to do so in WPF is using DataTemplate.
Representing the Hierarchical Data
Every
Master-Detail pattern requires a data structure. As an example of a
hierarchical data-structure, I’ve chosen to use the following hypothetical
Hi-Tech company:
The
company is comprised of three departments:
- Management: CEO, CTO, VP.QA
- Development: CTO and subordinates on the development team.
- QA: VP of QA and subordinates on the QA team.
For this example, I've chosen to take the aspect of the departments, i.e. every row in the view is a different department:
Let's look at the classes:
public class Employee
{
public Employee()
{
Subordinates = new List<Employee>();
}
public List<Employee> Subordinates { get; set; }
public string Name
{
get;
set;
}
public override string ToString()
{
return this.Name;
}
}
Each
employee includes “subordinates” which is a collection of employees.
public class Department : INotifyPropertyChanged
{
public Department()
{
Employees = new List<Employee>();
}
public List<Employee> Employees { get; set; }
protected int m_EmployeesSelectedIndex = 0;
public int EmployeesSelectedIndex
{
get
{
return m_EmployeesSelectedIndex;
}
set
{
m_EmployeesSelectedIndex = value;
NotifyPropertyChanged("Subordinates");
}
}
public List<Employee> Subordinates
{
get
{
List<Employee> res = null;
if (Employees.Count > 0)
{
res = Employees[EmployeesSelectedIndex].Subordinates;
}
return res;
}
}
public string Name
{
get;
set;
}
public override string ToString()
{
return this.Name;
}
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Every
department includes a collection of the employees working there.
The Department class also contains the following members:
- EmployeesSelectedIndex
- Subordinates list
- NotifyPropertyChanged mechanism
All
of these are used for implementing the Master-Detail Logic, and will be explained
in the section "Master-Detail Logic" below.
For
the sake of simplicity, we are presenting the data inside an ItemsControl:
<!-- Data rows -->
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" MinWidth="320">
<TextBlock Width="130" Text="{Binding Name}"/>
<ComboBox Width="130" ItemsSource="{Binding Employees}" SelectedIndex="{Binding EmployeesSelectedIndex}" />
<ComboBox Width="130" ItemsSource="{Binding Subordinates}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So what we are dealing with here is simply a DataTemplate with:
- TextBlock - For the department name.
- ComboBox - For the departments’ employees’ names.
- ComboBox - For the selected employee’s subordinates.
Please Notice: In the code sample attached for download, there are also headers, borders & other simple UI decorations for each data item, but the logic is the same.
It should look like this:
Master-Detail Logic:
We need to connect the selection of a particular employee to that employee’s subordinates list.
That is why the Department class contains:
- EmployeesSelectedIndex
- Subordinates list
- NotifyPropertyChanged mechanism
Let’s see how it works:
About the examples for download:
The examples for download are a bit more complicated:
Master-Detail Simple file also contains:
- Headers, borders & other simple UI decorations for each data item.
- Subordinates Selected-Index for default selection of the first index in the Subordinates Combo-Box.
- Subordinates Is-Enabled for disabling the Subordinates Combo-Box when there are no Items.

- Download Hierarchical_MasterDetail_Simple-noexe.zip - 26.6 KB
- Download Hierarchical_MasterDetail_Simple.zip - 61.5 KB
Master-Detail Advanced file also contains:
- all of the above (from the Simple example)
- Employee-Image & Subordinate-Image