views:

3021

answers:

4

Hi all,

I'm using the TreeView component from the Silverlight toolkit and I'm trying to get the parent of a selected node. The TreeView is bound to a series of objects, so directly working with a TreeViewItem appears to be out of the question.

<toolkit:TreeView SelectedItemChanged="DoStuff" DisplayMemberPath="Name" ItemsSource="{Binding MyCollection}">
    <toolkit:TreeView.ItemTemplate>
     <common:HierarchicalDataTemplate ItemsSource="{Binding MySubCollection}">
      <StackPanel>
       <TextBlock Text="{Binding Name}" />
      </StackPanel>
     </common:HierarchicalDataTemplate>
    </toolkit:TreeView.ItemTemplate>
</toolkit:TreeView>

Is there a way to fetch the parent of an item selected in the DoStuff event?

+1  A: 

Why don't you just have the objects in MySubcollection keep a reference to their parent?

Graeme Bradbury
That's the sensible thing to do, but doesn't answer the question. :)
Gabriel Isenberg
A: 

Suppose your Tree's name is "tree", this should do the trick

((tree.SelectedItem as TreeViewItem).Parent as SomeObjectOfYours)
I don't think that this will work. Assuming the OP is using data binding, tree.SelectedItem will return the bound object rather than the TreeViewItem.
Andy
A: 

Justin Angel wrote about "advanced" TreeView uses, among them finding arbirtraty elements in a treeview by their bound object. Since I am comparatively new to Silverlight, I am not sure if there is a better, more elegant way, but you could use one of his methods to find the parent.

I imagine using a call this way:

TreeViewItem trvi = ContainerFromItem(tree, tree.SelectedItem);
MySubCollectionItem parentItem = ItemFromContainer(tree, trvi.Parent); // note the "Parent" here

With the extension methods below available from somewhere:

public static TreeViewItem ContainerFromItem(this TreeView treeView, object item)
{
    TreeViewItem containerThatMightContainItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(item);
    if (containerThatMightContainItem != null)
        return containerThatMightContainItem;
    else
        return ContainerFromItem(treeView.ItemContainerGenerator, treeView.Items, item);
}

private static TreeViewItem ContainerFromItem(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, object item)
{
    foreach (object curChildItem in itemCollection)
    {
        TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem);
        if (parentContainer == null)
            return null;
        TreeViewItem containerThatMightContainItem = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item);
        if (containerThatMightContainItem != null)
            return containerThatMightContainItem;
        TreeViewItem recursionResult = ContainerFromItem(parentContainer.ItemContainerGenerator, parentContainer.Items, item);
        if (recursionResult != null)
            return recursionResult;
    }
    return null;
}

public static object ItemFromContainer(this TreeView treeView, TreeViewItem container)
{
    TreeViewItem itemThatMightBelongToContainer = (TreeViewItem)treeView.ItemContainerGenerator.ItemFromContainer(container);
    if (itemThatMightBelongToContainer != null)
        return itemThatMightBelongToContainer;
    else
        return ItemFromContainer(treeView.ItemContainerGenerator, treeView.Items, container);
}

private static object ItemFromContainer(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, TreeViewItem container)
{
    foreach (object curChildItem in itemCollection)
    {
        TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem);
        if (parentContainer == null)
            return null;
        TreeViewItem itemThatMightBelongToContainer = (TreeViewItem)parentContainer.ItemContainerGenerator.ItemFromContainer(container);
        if (itemThatMightBelongToContainer != null)
            return itemThatMightBelongToContainer;
        TreeViewItem recursionResult = ItemFromContainer(parentContainer.ItemContainerGenerator, parentContainer.Items, container) as TreeViewItem;
        if (recursionResult != null)
            return recursionResult;
    }
    return null;
}
ClearsTheScreen
+3  A: 

As long as you've downloaded the latest Silverlight Toolkit then this is easy using the TreeViewExtensions that are included.

  1. Download the Silverlight Toolkit and install.
  2. Add a reference to System.Windows.Controls.Toolkit (from the Silverlight Toolkit)
  3. Use the GetParentItem() extension method, like so:

    private void DoStuff(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (e.NewValue != null)
        {
            var parent = ((TreeView)sender).GetParentItem(e.NewValue);
            //
            // Do stuff with parent, this snippet updates 
            // a TextBlock showing the name of the current parent
            if (parent != null)
            {
                 Status.Text = parent.ToString();
            }
        }
    }
    
Shawn Oster