Posted by: Zeeshan Amjad | March 7, 2010

Relative Binding


We saw the example of master detail data binding here and here. Now we want to add one more functionality in that program. If we want to display the state name as well as county name on the top of list view. But if we are going to do the data binding on the Name property in the text box then it will display the name of the county not the state. Because at that level we have the selected county in the tree control.

We want to display the name of the state all the time and the name of sate is available at the window level. Now we can use the the relative binding feather of WPF. In Relative binding we use the FindAncestor property of binding to traverse the logical tree upward. We can further filter the the logical tree item by defining AncestorType property. Here is a piece of XAML code to do the data binding on the ancestor level where item type is Window.

  1: <Border Grid.Row="0" Margin="5" Background="Wheat"
  2: 		DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}">
  3: 	<TextBlock VerticalAlignment="Center" FontSize="18"
  4: 	Text="{Binding Name}"/>
  5: </Border>
  6: 

We define the text box inside the border control to do the data binding on Name property of DatacContext of Border control. Border control itself with the Window type of DataContext. Here is a complete XAML code of 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:             <Grid.RowDefinitions>
 38:                 <RowDefinition/>
 39:                 <RowDefinition/>
 40:                 <RowDefinition Height="5*"/>
 41:             </Grid.RowDefinitions>
 42:             <Border Grid.Row="0" Margin="5" Background="Wheat"
 43:                     DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}">
 44:                 <TextBlock VerticalAlignment="Center" FontSize="18"
 45:                 Text="{Binding Name}"/>
 46:             </Border>
 47:             <TextBlock Grid.Row="1" Margin="5" VerticalAlignment="Center" FontSize="14"
 48:                        Background="LightYellow" Text="{Binding Name}"/>
 49:             <TextBlock Grid.Row="1"/>
 50:             <ListView Grid.Row="2" ItemsSource="{Binding Path=Cities}" 
 51:                       AlternationCount="2" ItemContainerStyle="{StaticResource alternateColor}">
 52:                 <ListView.View>
 53:                     <GridView>
 54:                         <GridView.ColumnHeaderTemplate>
 55:                             <DataTemplate>
 56:                                 <TextBlock FontWeight="Bold" Margin="5" Text="{Binding}"/>
 57:                             </DataTemplate>
 58:                         </GridView.ColumnHeaderTemplate>
 59: 
 60:                         <GridViewColumn Width="Auto" Header="Name" DisplayMemberBinding="{Binding Path=Name}"/>
 61:                         <GridViewColumn Width="Auto" Header="Population" DisplayMemberBinding="{Binding Path=Population}"/>
 62:                         <GridViewColumn Width="Auto" Header="Area" DisplayMemberBinding="{Binding Path=Area}"/>
 63:                     </GridView>
 64:                 </ListView.View>
 65:             </ListView>
 66:         </Grid>
 67:     </Grid>
 68: </Window>
 69: 

Here is complete C# coding 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.Population = "5,699,478";
 60:             state1.Counties = countyList1;
 61: 
 62:             state1.Counties = countyList1;
 63: 
 64:             states.Add(state1);
 65: 
 66:             DataContext = states;
 67:         }
 68:     }
 69: 
 70:     public class City
 71:     {
 72:         public City()
 73:         {
 74:         }
 75: 
 76:         public City(String name, String population, String area)
 77:         {
 78:             Name = name;
 79:             Population = population;
 80:             Area = area;
 81:         }
 82: 
 83:         public String Name
 84:         { get; set; }
 85: 
 86:         public String Population
 87:         { get; set; }
 88: 
 89:         public String Area
 90:         { get; set; }
 91:     }
 92: 
 93:     public class CityList : ObservableCollection<City>
 94:     {
 95:     }
 96: 
 97:     public class County
 98:     {
 99:         public County()
100:         {
101:             Cities = new CityList();
102:         }
103: 
104:         public String Name
105:         { get; set; }
106: 
107:         public String Population
108:         { get; set; }
109: 
110:         public String Area
111:         { get; set; }
112: 
113:         public CityList Cities
114:         { get; set; }
115:     }
116: 
117:     public class CountyList : ObservableCollection<County>
118:     {
119:     }
120: 
121:     public class State
122:     {
123:         public State()
124:         {
125:             Counties = new CountyList();
126:         }
127: 
128:         public String Name
129:         { get; set; }
130: 
131:         public String Population
132:         { get; set; }
133: 
134:         public String NickName
135:         { get; set; }
136: 
137:         public CountyList Counties
138:         { get; set; }
139:     }
140: 
141:     public class StateList : ObservableCollection<State>
142:     {
143:     }
144: }
145: 

This is the output of the program.

MasterDetailTreeListView_03

Advertisements

Responses

  1. […] Binding Revisited We saw an example of relative binding here. In that sample we used the FindAncestor type when using RelativeSource markup extension. We can do […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: