Posted by: Zeeshan Amjad | March 4, 2010

Master Detail Relationship between Tree and ListView


 

We have already saw the example of master detail relationship between two list boxes here. We also saw one example of master detail data binding using LINQ here. This time we are going to implement the master detail relationship between tree and list view control. In fact we have already saw one example that is closely related to this here but in that example we are using LINQ to get the detail data.

First we have to create a nested data structure. Here is our classes to store the nested data structure.

  1: public class City
  2: {
  3:     public City()
  4:     {
  5:     }
  6: 
  7:     public City(String name, String population, String area)
  8:     {
  9:         Name = name;
 10:         Population = population;
 11:         Area = area;
 12:     }
 13: 
 14:     public String Name
 15:     { get; set; }
 16: 
 17:     public String Population
 18:     { get; set; }
 19: 
 20:     public String Area
 21:     { get; set; }
 22: }
 23: 
 24: public class CityList : ObservableCollection<City>
 25: {
 26: }
 27: 
 28: public class County
 29: {
 30:     public County()
 31:     {
 32:         Cities = new CityList();
 33:     }
 34: 
 35:     public String Name
 36:     { get; set; }
 37: 
 38:     public String Population
 39:     { get; set; }
 40: 
 41:     public String Area
 42:     { get; set; }
 43: 
 44:     public CityList Cities
 45:     { get; set; }
 46: }
 47: 
 48: public class CountyList : ObservableCollection<County>
 49: {
 50: }
 51: 
 52: public class State
 53: {
 54:     public State()
 55:     {
 56:         Counties = new CountyList();
 57:     }
 58: 
 59:     public String Name
 60:     { get; set; }
 61: 
 62:     public String NickName
 63:     { get; set; }
 64: 
 65:     public CountyList Counties
 66:     { get; set; }
 67: }
 68: 
 69: public class StateList : ObservableCollection<State>
 70: {
 71: }
 72: 

Now we do the data binding of tree view control. Here we simply define the hierarchical data template.

  1: <TreeView  Name="tree" Grid.Column="0" Margin="5" ItemsSource="{Binding}">
  2: 	<TreeView.ItemTemplate>
  3: 		<HierarchicalDataTemplate ItemsSource="{Binding Counties}">
  4: 			<TextBlock Text="{Binding Path=Name}"/>
  5: 			
  6: 			<HierarchicalDataTemplate.ItemTemplate>
  7: 				<HierarchicalDataTemplate ItemsSource="{Binding Cities}">
  8: 					<TextBlock Text="{Binding Path=Name}"/>                            
  9: 				</HierarchicalDataTemplate>
 10: 			</HierarchicalDataTemplate.ItemTemplate>
 11: 			
 12: 		</HierarchicalDataTemplate>
 13: 	</TreeView.ItemTemplate>
 14: </TreeView>
 15: 

Now we are going to define the binding for the list view. Here we use one small trick. Instead of perform the data binding on selected item of tree control directly, we set the selected item of tree control as a data context of grid.

  1: <Grid Grid.Column="1" Margin="5" DataContext="{Binding ElementName=tree, Path=SelectedItem}">

Now we define the list box inside the grid view.

  1: <ListView ItemsSource="{Binding Path=Cities}" 
  2:   AlternationCount="2" ItemContainerStyle="{StaticResource alternateColor}">

Here is a complete XAML code of the program.

  1: <Window x:Class="WpfMasterDetail.Window1"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:     Title="Master Detail" Height="400" Width="600">
  5:     <Window.Resources>
  6:         <Style x:Key="alternateColor" TargetType="{x:Type ListViewItem}">
  7:             <Style.Triggers>
  8:                 <Trigger Property="ItemsControl.AlternationIndex" Value="0">
  9:                     <Setter Property="Background" Value="LightBlue"/>
 10:                 </Trigger>
 11:                 <Trigger Property="ItemsControl.AlternationIndex" Value="1">
 12:                     <Setter Property="Background" Value="AliceBlue"/>
 13:                 </Trigger>
 14:             </Style.Triggers>
 15:         </Style>
 16:     </Window.Resources>
 17:     <Grid>
 18:         <Grid.ColumnDefinitions>
 19:             <ColumnDefinition/>
 20:             <ColumnDefinition Width="2*" />
 21:         </Grid.ColumnDefinitions>
 22:         <TreeView  Name="tree" Grid.Column="0" Margin="5" ItemsSource="{Binding}">
 23:             <TreeView.ItemTemplate>
 24:                 <HierarchicalDataTemplate ItemsSource="{Binding Counties}">
 25:                     <TextBlock Text="{Binding Path=Name}"/>
 26:                     
 27:                     <HierarchicalDataTemplate.ItemTemplate>
 28:                         <HierarchicalDataTemplate ItemsSource="{Binding Cities}">
 29:                             <TextBlock Text="{Binding Path=Name}"/>                            
 30:                         </HierarchicalDataTemplate>
 31:                     </HierarchicalDataTemplate.ItemTemplate>
 32:                     
 33:                 </HierarchicalDataTemplate>
 34:             </TreeView.ItemTemplate>
 35:         </TreeView>
 36:         <Grid Grid.Column="1" Margin="5" DataContext="{Binding ElementName=tree, Path=SelectedItem}">
 37:             <ListView ItemsSource="{Binding Path=Cities}" 
 38:                       AlternationCount="2" ItemContainerStyle="{StaticResource alternateColor}">
 39:                 <ListView.View>
 40:                     <GridView>
 41:                         <GridView.ColumnHeaderTemplate>
 42:                             <DataTemplate>
 43:                                 <TextBlock FontWeight="Bold" Margin="5" Text="{Binding}"/>
 44:                             </DataTemplate>
 45:                         </GridView.ColumnHeaderTemplate>
 46: 
 47:                         <GridViewColumn Width="Auto" Header="Name" DisplayMemberBinding="{Binding Path=Name}"/>
 48:                         <GridViewColumn Width="Auto" Header="Population" DisplayMemberBinding="{Binding Path=Population}"/>
 49:                         <GridViewColumn Width="Auto" Header="Area" DisplayMemberBinding="{Binding Path=Area}"/>
 50:                     </GridView>
 51:                 </ListView.View>
 52:             </ListView>
 53:         </Grid>
 54:     </Grid>
 55: </Window>
 56: 

And here is complete C# code of the program.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.Windows;
  6: using System.Windows.Controls;
  7: using System.Windows.Data;
  8: using System.Windows.Documents;
  9: using System.Windows.Input;
 10: using System.Windows.Media;
 11: using System.Windows.Media.Imaging;
 12: using System.Windows.Navigation;
 13: using System.Windows.Shapes;
 14: using System.Collections.ObjectModel;
 15: 
 16: namespace WpfMasterDetail
 17: {
 18:     /// <summary>
 19:     /// Interaction logic for Window1.xaml
 20:     /// </summary>
 21:     public partial class Window1 : Window
 22:     {
 23:         private StateList states = new StateList();
 24: 
 25:         public Window1()
 26:         {
 27:             InitializeComponent();
 28: 
 29:             CountyList countyList1 = new CountyList();
 30:             County county1 = new County();
 31:             county1.Name = "Frederick";
 32:             county1.Area = "667 sq mi";
 33:             county1.Population = "220,701";
 34:             CityList cities1 = new CityList();
 35:             cities1.Add(new City("Frederick", "59,220", "20.4 sq mi"));
 36:             cities1.Add(new City("Brunswick", "4,894", "2.1 sq mi"));
 37:             cities1.Add(new City("Middletown", "2,668", "1.7 sq mi"));
 38:             cities1.Add(new City("New Market", "427", "0.7 sq mi"));
 39:             county1.Cities = cities1;
 40: 
 41:             countyList1.Add(county1);
 42: 
 43:             County county2 = new County();
 44:             county2.Name = "Montgomery";
 45:             county2.Area = "507 sq mi";
 46:             county2.Population = "950,680";
 47:             CityList cities2 = new CityList();
 48:             cities2.Add(new City("Gaithersburg", "58,744", "10.2 sq mi"));
 49:             cities2.Add(new City("Rockville", "60,734", "13.4 sq mi"));
 50:             cities2.Add(new City("Takoma Park", "17,299", "2.36 sq mi"));
 51:             cities2.Add(new City("Chevy Chase", "2,726", "0.5 sq mi"));
 52:             county2.Cities = cities2;
 53: 
 54:             countyList1.Add(county2);
 55: 
 56:             State state1 = new State();
 57:             state1.Name = "Maryland";
 58:             state1.NickName = "Old Line State";
 59:             state1.Counties = countyList1;
 60: 
 61:             state1.Counties = countyList1;
 62: 
 63:             states.Add(state1);
 64: 
 65:             DataContext = states;
 66:         }
 67:     }
 68: 
 69:     public class City
 70:     {
 71:         public City()
 72:         {
 73:         }
 74: 
 75:         public City(String name, String population, String area)
 76:         {
 77:             Name = name;
 78:             Population = population;
 79:             Area = area;
 80:         }
 81: 
 82:         public String Name
 83:         { get; set; }
 84: 
 85:         public String Population
 86:         { get; set; }
 87: 
 88:         public String Area
 89:         { get; set; }
 90:     }
 91: 
 92:     public class CityList : ObservableCollection<City>
 93:     {
 94:     }
 95: 
 96:     public class County
 97:     {
 98:         public County()
 99:         {
100:             Cities = new CityList();
101:         }
102: 
103:         public String Name
104:         { get; set; }
105: 
106:         public String Population
107:         { get; set; }
108: 
109:         public String Area
110:         { get; set; }
111: 
112:         public CityList Cities
113:         { get; set; }
114:     }
115: 
116:     public class CountyList : ObservableCollection<County>
117:     {
118:     }
119: 
120:     public class State
121:     {
122:         public State()
123:         {
124:             Counties = new CountyList();
125:         }
126: 
127:         public String Name
128:         { get; set; }
129: 
130:         public String NickName
131:         { get; set; }
132: 
133:         public CountyList Counties
134:         { get; set; }
135:     }
136: 
137:     public class StateList : ObservableCollection<State>
138:     {
139:     }
140: }
141: 

 

This is the output of the program.

 

MasterDetailTreeListView


Responses

  1. […] ListView Revisited We saw the example of master detail relationship with tree and list view here. In that example we saw a we use the extra grid to the selected item binding with list view. We can […]

  2. can you send me the sourcecode ?


Leave a comment

Categories