How to bind an ancestor from a datatemplate generated descendant
- Hello to the forum,
I have a listbox whose data source is a collection of items (collection A).
Every item of the collection includes itself another collection of elements (collection B).
I use a datatemplate to present the listbox as a stack of blocks and to display inside
each block a tree of elements whose data source is the collection B.
If selecting a node of the datatemplate generated sub-tree,
I want the container listbox item to be selected as well.
Is it possible to bind ancestors' properties using as source the template-generated
descendants' properties?
I wasn't able to find a solution for this issue.
This is the xaml of my datatempate:
<DataTemplate x:Key="listBoxTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="tbxRole" Grid.Row="0" Grid.Column="0" Text="{Binding Path=ValueMember.Type.Name}"/>
<TreeView Name="subTree" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Path=ChildrenItems}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="root" ItemsSource="{Binding Path=ChildrenItems}">
<StackPanel Orientation="Horizontal">
<TextBlock Name="linkTypeName" Text="{Binding Path=ValueMember.LinkType.Name}"/>
<TextBlock Name="linkName" Text="{Binding Path=ValueMember.IdentityRefChild.LastName}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</DataTemplate>
Thanks for help in advance.
Gianni
Answers
You can get ListBoxItem from TreeView.GotFocus event. The following code shows how to do this.
Code Snippet<Window
x:Class="ForumProjects.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ForumProjects"
x:Name="Window">
<Window.Resources>
<DataTemplate x:Key="OrderItemTemplate">
<TextBlock Text="{Binding Product}"/>
</DataTemplate>
<HierarchicalDataTemplate x:Key="OrderTemplate"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource OrderItemTemplate}">
<TextBlock Text="{Binding OrderID}"/>
</HierarchicalDataTemplate>
<DataTemplate x:Key="CustomerTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TreeView ItemsSource="{Binding Orders}"
ItemTemplate="{StaticResource OrderTemplate}"
GotFocus="TreeViewGotFocus"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding ElementName=Window, Path=Customers}"
ItemTemplate="{StaticResource CustomerTemplate}"/>
</Window>
namespace ForumProjects
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.Customers = new List<Customer>()
{
new Customer("Customer A"),
new Customer("Customer B")
};
this.Customers[0].Orders.AddRange(new Order[]
{
new Order("0001"),
new Order("0002")
});
this.Customers[0].Orders[0].Items.AddRange(new OrderItem[]
{
new OrderItem("Product A"),
new OrderItem("Product B")
});
this.Customers[0].Orders[1].Items.AddRange(new OrderItem[]
{
new OrderItem("Product C"),
new OrderItem("Product D")
});
this.Customers[1].Orders.AddRange(new Order[]
{
new Order("0001"),
new Order("0002")
});
this.Customers[1].Orders[0].Items.AddRange(new OrderItem[]
{
new OrderItem("Product A"),
new OrderItem("Product B")
});
this.Customers[1].Orders[1].Items.AddRange(new OrderItem[]
{
new OrderItem("Product C"),
new OrderItem("Product D")
});
InitializeComponent();
}
private void TreeViewGotFocus(object sender, RoutedEventArgs e)
{
ContentPresenter presenter = (ContentPresenter)(((StackPanel)((TreeView)e.Source).Parent).TemplatedParent);
Customer customer = (Customer)presenter.Content;
((ListBox)this.Content).SelectedItem = customer;
}
public List<Customer> Customers { get; private set; }
}
public class Customer
{
public Customer(string name) { this.Orders = new List<Order>(); this.Name = name; }
public string Name { get; set; }
public List<Order> Orders { get; private set; }
}
public class Order
{
public Order(string id) { this.Items = new List<OrderItem>(); this.OrderID = id; }
public string OrderID { get; set; }
public List<OrderItem> Items { get; private set; }
}
public class OrderItem
{
public OrderItem(string product) { this.Product = product; }
public string Product { get; set; }
}
}
Best Regards,
Wei Zhou
All Replies
You can get ListBoxItem from TreeView.GotFocus event. The following code shows how to do this.
Code Snippet<Window
x:Class="ForumProjects.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ForumProjects"
x:Name="Window">
<Window.Resources>
<DataTemplate x:Key="OrderItemTemplate">
<TextBlock Text="{Binding Product}"/>
</DataTemplate>
<HierarchicalDataTemplate x:Key="OrderTemplate"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource OrderItemTemplate}">
<TextBlock Text="{Binding OrderID}"/>
</HierarchicalDataTemplate>
<DataTemplate x:Key="CustomerTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TreeView ItemsSource="{Binding Orders}"
ItemTemplate="{StaticResource OrderTemplate}"
GotFocus="TreeViewGotFocus"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding ElementName=Window, Path=Customers}"
ItemTemplate="{StaticResource CustomerTemplate}"/>
</Window>
namespace ForumProjects
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.Customers = new List<Customer>()
{
new Customer("Customer A"),
new Customer("Customer B")
};
this.Customers[0].Orders.AddRange(new Order[]
{
new Order("0001"),
new Order("0002")
});
this.Customers[0].Orders[0].Items.AddRange(new OrderItem[]
{
new OrderItem("Product A"),
new OrderItem("Product B")
});
this.Customers[0].Orders[1].Items.AddRange(new OrderItem[]
{
new OrderItem("Product C"),
new OrderItem("Product D")
});
this.Customers[1].Orders.AddRange(new Order[]
{
new Order("0001"),
new Order("0002")
});
this.Customers[1].Orders[0].Items.AddRange(new OrderItem[]
{
new OrderItem("Product A"),
new OrderItem("Product B")
});
this.Customers[1].Orders[1].Items.AddRange(new OrderItem[]
{
new OrderItem("Product C"),
new OrderItem("Product D")
});
InitializeComponent();
}
private void TreeViewGotFocus(object sender, RoutedEventArgs e)
{
ContentPresenter presenter = (ContentPresenter)(((StackPanel)((TreeView)e.Source).Parent).TemplatedParent);
Customer customer = (Customer)presenter.Content;
((ListBox)this.Content).SelectedItem = customer;
}
public List<Customer> Customers { get; private set; }
}
public class Customer
{
public Customer(string name) { this.Orders = new List<Order>(); this.Name = name; }
public string Name { get; set; }
public List<Order> Orders { get; private set; }
}
public class Order
{
public Order(string id) { this.Items = new List<OrderItem>(); this.OrderID = id; }
public string OrderID { get; set; }
public List<OrderItem> Items { get; private set; }
}
public class OrderItem
{
public OrderItem(string product) { this.Product = product; }
public string Product { get; set; }
}
}
Best Regards,
Wei Zhou


