Wednesday, October 17, 2012

TreeViewItem.ItemContainerGenerator.ContainerFromItem inconsistent results

TreeViewItem.ItemContainerGenerator.ContainerFromItem inconsistent results

I have a TreeView on my page. It's bound to a collection of clients containing contracts, like:

public class Client {   public int ClientID { get; set; }   public string Name { get; set; }   public List<Contract> Contracts { get; set; } }  public class Contract {   public int ContractID { get; set; }   public int ClientID { get; set; }   public string Name { get; set; } } 

The XAML for my TreeView is as follows:

<sdk:TreeView x:Name="tvClientContract" ItemsSource="{Binding ClientContracts}">   <sdk:TreeView.ItemTemplate>     <sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Contracts}">       <TextBlock Text="{Binding Path=Name}" />     </sdk:HierarchicalDataTemplate>   </sdk:TreeView.ItemTemplate> </sdk:TreeView> 

Where ClientContracts is a List<Clients>. The binding works fine and I have a hierarchical grid.

The issue that I'm having is when opening the form with the TreeView on it I want to select the current Client, I currently use the following code:

TreeViewItem client = (TreeViewItem)tvClientContract.ItemContainerGenerator.ContainerFromItem(aClient); 

or

TreeViewItem client = (TreeViewItem)tvClientContract.ItemContainerGenerator.ContainerFromIndex(tvClientContract.Items.IndexOf(aClient)); client.IsSelected = true; 

but this returns inconsistent results, for example I open the form when client 'ABC' is selected and client will be null. I open it again when client 'ABC' is selected and it returns the correct TreeViewItem. Has anyone came across this before or know anything I can look at to help solve the issue?

I run the above code within the Loaded event of the TreeView.

Answers & Comments...

Answer: 1

I figured out what's happening here, the clue is in the MSDN documentation for the return value of ItemContainerGenerator.ContainerFromItem():

A UIElement that corresponds to the given item. Returns null if the item does not belong to the item collection, or if a UIElement has not been generated for it.

It looks like when null is returned, a UIElement hasn't been created for the item yet.

I got round this by using

tvClientContract.UpdateLayout();

to update the layout and ensure a UIElement exists before calling

ItemContainerGenerator.ContainerFromItem() 
by : Ferminhttp://stackoverflow.com/users/83096

Answer: 2

I think that there could be some condition where "UpdateLoayout will not work": if the TreeView is in recycling mode and the item is not in the visible portion and/or also in a "add" operation where the TreeViewItem is created on another thread.

The solution is to use similar solution as I describe in: WPF: Select TreeViewItem broken past the root level

by : Eric Ouellethttp://stackoverflow.com/users/452845




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog