Objective
In this Article our objective is to display a list of person objects in treeview. We will provide a AddPerson button in UI. When we click on the AddPerson button, a new Item should add in List<Person> object and same should reflect in UI as shown below,
Before starting your project create 3 folders under your WPF new project like below and delete MainWinow.xaml class
Create a Person class in Model Folder
- namespace TreeviewBindingAPP.Model
- {
- public class Person
- {
- public string Name { get; set; }
- public int Age { get; set; }
- public string Gender { get; set; }
- }
- }
Create PersonViewModel.cs Class in ViewModel folder and inherit INotifyPropertyChanged Interface and provide implantation as below.
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Windows.Input;
- using TreeviewBindingAPP.Commands;
- using TreeviewBindingAPP.Model;
-
- namespace TreeviewBindingAPP.ViewModel
- {
- public class PersonViewModel : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler PropertyChanged;
-
- public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
-
- private List<Person> _persons;
- public List<Person> Persons
- {
- get => _persons;
- set
- {
- _persons = value;
- OnPropertyChanged(nameof(Persons));
- }
- }
-
- private ICommand command;
- public ICommand ActionCommand
- {
- get => command ?? new RelayCommand(this);
- }
- }
- }
Create RelayCommand class in Commands folder and inherit ICommand Interface and provide implementation as shown below
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Windows.Input;
- using TreeviewBindingAPP.Model;
- using TreeviewBindingAPP.ViewModel;
-
- namespace TreeviewBindingAPP.Commands
- {
- public class RelayCommand : ICommand
- {
- PersonViewModel _personViewModel;
-
- public RelayCommand(PersonViewModel personViewModel)
- {
- _personViewModel = personViewModel;
- }
-
- public event EventHandler CanExecuteChanged;
-
- public bool CanExecute(object parameter) => true;
-
- public void Execute(object parameter)
- {
- if (parameter is null)
- return;
-
- string action = parameter.ToString();
- switch(action)
- {
- case "AddPerson":
- AddPersons();
- break;
- }
- }
-
- private void AddPersons()
- {
- if (_personViewModel.Persons is null)
- _personViewModel.Persons = new List<Person>();
-
- var temp = _personViewModel.Persons;
- _personViewModel.Persons = new List<Person>();
-
- temp.Add(new Person
- {
- Name = "ABC_" + temp.Count() + 1,
- Age = int.Parse(DateTime.Now.ToString("ss")),
- Gender = "Male"
- });
- _personViewModel.Persons = temp;
- }
- }
- }
Create PersonView.xaml window in View folder and provide implementation in XAML as shown below and In App.xaml file update StartupUri as StartupUri="View/PersonView.xaml"
- <Window x:Class="TreeviewBindingAPP.View.PersonView"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:viemModel="clr-namespace:TreeviewBindingAPP.ViewModel" BorderBrush="Black" BorderThickness="1"
- mc:Ignorable="d" SizeToContent="WidthAndHeight" WindowStyle="None" AllowsTransparency="True" MouseDown="Window_MouseDown"
- Title="PersonView" MinHeight="600" MinWidth="800">
- <Window.DataContext>
- <viemModel:PersonViewModel/>
- </Window.DataContext>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="30"/>
- <RowDefinition Height="80*"/>
- <RowDefinition Height="30"/>
- </Grid.RowDefinitions>
-
- <Grid Grid.Row="0" Background="Orange">
- <Label Content="Bind Custom object List to Treeview" FontSize="14" Foreground="White" FontWeight="SemiBold"/>
- <Button Height="24" Width="24" Name="btnClose" HorizontalAlignment="Right" FontWeight="Bold" Cursor="Hand"
- VerticalAlignment="Center" Content="X" Click="BtnClose_Click" Focusable="False" Background="{x:Null}" Foreground="White" />
- <x:Code>
- private void BtnClose_Click(object sender, RoutedEventArgs e)
- {
- Close();
- }
- private void Window_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
- {
- try
- {
- this.DragMove();
- }
- catch
- {
- }
- }
- </x:Code>
- </Grid>
- <Grid Grid.Row="1">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="20*"/>
- <ColumnDefinition Width="80*"/>
- </Grid.ColumnDefinitions>
- <Grid Grid.Column="0">
- <StackPanel Orientation="Horizontal">
- <Grid Grid.Row="0" Background="White" >
- <Button Name="AddPerson" Height="30" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center" Background="{x:Null}" Content="Add person" Command="{Binding ActionCommand}" CommandParameter="{Binding ElementName=AddPerson, Path=Name}"/>
- </Grid>
- <Grid Grid.Row="1" Margin="100,0,0,0" >
- <TreeView Height="600" Width="200" FontSize="24" FontFamily="Segoe UI" HorizontalAlignment="Right" VerticalAlignment="Top" ItemsSource="{Binding Persons}">
- <TreeView.ItemTemplate>
- <HierarchicalDataTemplate>
- <TreeViewItem Header="{Binding Name}">
- <TreeViewItem Header="{Binding Gender}"/>
- <TreeViewItem Header="{Binding Age}"/>
- </TreeViewItem>
- </HierarchicalDataTemplate>
- </TreeView.ItemTemplate>
- </TreeView>
- </Grid>
- </StackPanel>
- </Grid>
- </Grid>
- <Grid Grid.Row="2" Background="DarkGray">
-
- </Grid>
- </Grid>
- </Window>
In above code we can see code for Treeview (same code copied in below)
- <TreeView Height="600" Width="200" FontSize="24" FontFamily="Segoe UI" HorizontalAlignment="Right" VerticalAlignment="Top" ItemsSource="{Binding Persons}">
- <TreeView.ItemTemplate>
- <HierarchicalDataTemplate>
- <TreeViewItem Header="{Binding Name}">
- <TreeViewItem Header="{Binding Gender}"/>
- <TreeViewItem Header="{Binding Age}"/>
- </TreeViewItem>
- </HierarchicalDataTemplate>
- </TreeView.ItemTemplate>
- </TreeView>
For Treeview control we are setting TreeView.ItemTemplate.
ItemTemplate is used to get or set the date for every TreeViewItem. For now we need to display data in a hierarchical way so in ItemTemplate again we need to HierarchicalDataTemplate class. Under HierarchicalDataTemplate tag we can mention how we want to display the custom object. For instance in our example we want to display Person Name as Header Item and inside that we will show Age and Gender of the Header bound person; i.e., when Name TreeViewItem is expanded, In UI we can see the Age and Gender
How is object added into TreeView?
As per MVVM, ViewModel is bind to View using Window.DataContext.
List<Person> Persons is created in ViewModel and did binding to TreeView’s ItemSource in PersonView.xaml class.
We added a button in UI called AddPerson and its command is bound to ActionCommand, which is defined in PersonViewModel with type ICommand. This is responsible to pass action performed in UI to RelayCommand class as RelayCommand is inherited by ICommand. So when we click on Button, Button will notify ActionCommand and ActionCommand will notify RelayCommand to perform method AddPersons.The movement new object is added in Persons object and Persons object will notify to UI as we already bound the Persons Object in xaml class and reflect in TreeView
Below is the execution window snap,
Summary
In this article welearned how to bind the custom list object to treeview and use of ItemTemplate and HierarchicalDataTemplate.