Populating Hierarchical Data In TreeView In WPF Using MVVM

Today, in this article, we will learn how to populate hierarchical data in TreeView in WPF using MVVM architecture.

Let’s take an example of populating employees’ details per position per department in hierarchical pattern.

Step1 Create new project

  • Create new WPF application and name it as “TreeViewMVVMBinding”.

    WPF

Step2 InotifyPropertyChanged Class

  • Add new class and name it as “ViewModelBase”. This is a base class to notify the client that a property value has changed.
  • Add code to handle “PropertyChangedEventHandler”.
  • Finally, class should be like below.
    1. public class ViewModelBase : INotifyPropertyChanged  
    2.     {  
    3.         public event PropertyChangedEventHandler PropertyChanged;  
    4.   
    5.         public void OnPropertyChanged(string propname)  
    6.         {  
    7.             if (PropertyChanged != null)  
    8.             {  
    9.                 PropertyChanged(thisnew PropertyChangedEventArgs(propname));  
    10.             }  
    11.         }  
    12.     }  

Step3 Employee Class

  • Add new class and name it as “Employee”. This is a model class to define structure for employee.
  • Define properties for employee related details.
  • Inherit ViewBase class and implement Property changed notification while setting value of each property.
  • Finally, class should be like below.
    1. Public class Employee : ViewModelBase  
    2.     {  
    3.         private string _strEmployeeName = string.Empty;  
    4.         public string EmployeeName  
    5.         {  
    6.             get  
    7.             {  
    8.                 return _strEmployeeName;  
    9.             }  
    10.             set  
    11.             {  
    12.                 _strEmployeeName = value;  
    13.                 OnPropertyChanged("EmployeeName");  
    14.             }  
    15.         }  
    16.   
    17.         public Employee(string employeename)  
    18.         {  
    19.             EmployeeName = employeename;  
    20.         }  
    21.     }  

Step4 Position Class

  • Add new class and name it “Position”. This is a model class to define position of an employee in the company.
  • Define properties for position related details.
  • Inherit ViewBase class and implement Property changed notification while setting value of each property.
  • Finally, class should be like below.
    1. public class Position : ViewModelBase  
    2.     {  
    3.         private List<Employee> employees;  
    4.   
    5.         public Position(string positionname)  
    6.         {  
    7.             PositionName = positionname;  
    8.             employees = new List<Employee>()  
    9.             {  
    10.                 new Employee("Employee1"),  
    11.                 new Employee("Employee2"),  
    12.                 new Employee("Employee3")  
    13.             };  
    14.         }  
    15.   
    16.         public List<Employee> Employees  
    17.         {  
    18.             get  
    19.             {  
    20.                 return employees;  
    21.             }  
    22.             set  
    23.             {  
    24.                 employees = value;  
    25.                 OnPropertyChanged("Employees");  
    26.             }  
    27.         }  
    28.   
    29.         public string PositionName  
    30.         {  
    31.             get;  
    32.             set;  
    33.         }  
    34.     }  

Step5 Department Class

  • Add new class and name it “Department”. This is a model class to define structure for Department.
  • Define properties for Department related details.
  • Inherit ViewBase class and implement Property changed notification while setting the value of each property.
  • Finally, class should be like below.
    1. public class Department : ViewModelBase  
    2.     {  
    3.         private List<Position> positions;  
    4.   
    5.         public Department(string depname)  
    6.         {  
    7.             DepartmentName = depname;  
    8.             positions = new List<Position>()  
    9.             {  
    10.                 new Position("TL"),  
    11.                 new Position("PM")  
    12.             };  
    13.         }  
    14.         public List<Position> Positions  
    15.         {  
    16.             get  
    17.             {  
    18.                 return positions;  
    19.             }  
    20.             set  
    21.             {  
    22.                 positions = value;  
    23.                 OnPropertyChanged("Positions");  
    24.             }  
    25.         }  
    26.         public string DepartmentName  
    27.         {  
    28.             get;  
    29.             set;  
    30.         }  
    31.     }  

We are done with our base implementation for required details with required classes. Now, we will bind a set of these implementations into a TreeView to populate data in hierarchical format.

Step6 ViewModel for a window to bind datacontext

  • Add new class and name it as “MainWindowViewModel”. This will be a ViewModule for our View “MainWindow”.
  • Finally, class should be like below.
    1. public class MainWindowViewModel : ViewModelBase  
    2.     {  
    3.         private List<Department> departments;  
    4.   
    5.         public MainWindowViewModel()  
    6.         {  
    7.             Departments = new List<Department>()  
    8.             {  
    9.                 new Department("DotNet"),  
    10.                 new Department("PHP")  
    11.             };  
    12.         }  
    13.   
    14.         public List<Department> Departments  
    15.         {  
    16.             get  
    17.             {  
    18.                 return departments;  
    19.             }  
    20.             set  
    21.             {  
    22.                 departments = value;  
    23.                 OnPropertyChanged("Departments");  
    24.             }  
    25.         }  
    26.     }  

Step7 Prepare View

  • Add Namespace of current application in MainWindow Xaml file.
    1. xmlns:VM="clr-namespace:TreeViewMVVMBinding"  
  • Bind MainWindowViewModel as DataContext to MainWindow View.
    1. <Window.DataContext>  
    2. <VM:MainWindowViewModel/>  
    3. </Window.DataContext>  
  • Add TreeView control into the MainWindow and name it as “MainTreeView”.
    1. <TreeView x:Name="MainTreeView" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch"/>  
  • Bind HierarchicalDataTemplate as per the data structure.
    1. <TreeView x:Name="MainTreeView" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch" ItemsSource="{Binding Departments}">  
    2.             <TreeView.ItemTemplate>  
    3.                 <HierarchicalDataTemplate ItemsSource="{Binding Positions}" DataType="{x:Type VM:Department}">  
    4.                     <Label Content="{Binding DepartmentName}"/>  
    5.                     <HierarchicalDataTemplate.ItemTemplate>  
    6.                         <HierarchicalDataTemplate ItemsSource="{Binding Employees}" DataType="{x:Type VM:Position}">  
    7.                             <Label Content="{Binding PositionName}"/>  
    8.                             <HierarchicalDataTemplate.ItemTemplate>  
    9.                                 <DataTemplate DataType="{x:Type VM:Employee}">  
    10.                                     <Label Content="{Binding EmployeeName}"/>  
    11.                                 </DataTemplate>  
    12.                             </HierarchicalDataTemplate.ItemTemplate>  
    13.                         </HierarchicalDataTemplate>  
    14.                     </HierarchicalDataTemplate.ItemTemplate>  
    15.                 </HierarchicalDataTemplate>  
    16.             </TreeView.ItemTemplate>  
    17.         </TreeView>  

Finally, complete the XAML code for MainWindow. The window will be as mentioned below.

  1. <Window x:Class="TreeViewMVVMBinding.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.         xmlns:local="clr-namespace:TreeViewMVVMBinding"  
  7.         xmlns:VM="clr-namespace:TreeViewMVVMBinding"  
  8.         mc:Ignorable="d"  
  9.         Title="MainWindow" Height="350" Width="525">  
  10.     <Window.DataContext>  
  11.         <VM:MainWindowViewModel/>  
  12.     </Window.DataContext>  
  13.     <Grid>  
  14.         <TreeView x:Name="MainTreeView" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch" ItemsSource="{Binding Departments}">  
  15.             <TreeView.ItemTemplate>  
  16.                 <HierarchicalDataTemplate ItemsSource="{Binding Positions}" DataType="{x:Type VM:Department}">  
  17.                     <Label Content="{Binding DepartmentName}"/>  
  18.                     <HierarchicalDataTemplate.ItemTemplate>  
  19.                         <HierarchicalDataTemplate ItemsSource="{Binding Employees}" DataType="{x:Type VM:Position}">  
  20.                             <Label Content="{Binding PositionName}"/>  
  21.                             <HierarchicalDataTemplate.ItemTemplate>  
  22.                                 <DataTemplate DataType="{x:Type VM:Employee}">  
  23.                                     <Label Content="{Binding EmployeeName}"/>  
  24.                                 </DataTemplate>  
  25.                             </HierarchicalDataTemplate.ItemTemplate>  
  26.                         </HierarchicalDataTemplate>  
  27.                     </HierarchicalDataTemplate.ItemTemplate>  
  28.                 </HierarchicalDataTemplate>  
  29.             </TreeView.ItemTemplate>  
  30.         </TreeView>  
  31.     </Grid>  
  32. </Window>  

We are done with the implementation. Run the application and check the output. It should be like the following.

WPF

Thank you. Please let me know if you have any query or concern regarding the above implementation. I hope I have explained enough for you to understand the concept.