使用数据绑定时如何从TreeView中提取SelectedItem?

时间:2013-04-21 20:07:25

标签: c# wpf xml treeview

我遵循本文的建议将树视图控件绑定到xml文档: http://www.codeproject.com/Articles/317766/Displaying-XML-in-a-WPF-TreeView?msg=4546407#xx4546407xx

但是,现在我无法弄清楚如何访问所选项目。

这是我的XAML:

<Window.Resources>
    <XmlDataProvider x:Key="xmldata" Source="cats.xml" XPath="/CategoryArray" />
    <HierarchicalDataTemplate DataType="Category" ItemsSource="{Binding XPath=./*}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Margin="5,0,0,0" Text="{Binding XPath=@Name}" Tag="{Binding XPath=@ID}" />
        </StackPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="CategoryArray" ItemsSource="{Binding XPath=./*}">
        <TextBlock Margin="0" Text="eBay Categories" />
    </HierarchicalDataTemplate>
</Window.Resources>
<Grid DataContext="{StaticResource xmldata}">
    <TreeView Name="treeView1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding}" VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Standard" SelectedItemChanged="treeView1_SelectedItemChanged" />
</Grid>

这似乎不像我想象的那样有效:

    private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        try
        {
            TreeViewItem selectedItem = treeView1.SelectedValue as TreeViewItem;
            categoryName = selectedItem.Name;
            categoryID = selectedItem.Tag.ToString();
            categoryChosen = true;
        }
        catch { }
    }

由于我使用的是这种分层数据模板和文本块,我不知道该怎么做。有任何想法吗?提前谢谢。

2 个答案:

答案 0 :(得分:0)

你应该摆脱所有的脏尝试。您可以使用e.NewValue并检查它是否是您指定的类型之一。由于您直接告诉WPF您的数据模型是什么,您可以像这样使用它:

private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    var category =  e.NewValue as Category;
    if(category != null)
    {
        //FIXME: do things if its Category
    }
    else
    {
        var categoryArray = e.NewValue as CategoryArray;
        if(categoryArray != null)
        {
            //FIXME: do things if its CategoryArray
        }
    }  
}

答案 1 :(得分:0)

使用XAML时,您可以使用绑定来检索框架元素的属性。但是在这种特殊情况下,TreeView的SelectedItem属性是只读的,因此您不能直接绑定它,但是您可以使用附加属性来实现相同的目的。

我试图为你的案子制作一个样本

在VM类中声明附加属性,并带有更改通知以执行您的逻辑

public static object GetSelectedTreeItem(DependencyObject obj)
{
    return (object)obj.GetValue(SelectedTreeItemProperty);
}

public static void SetSelectedTreeItem(DependencyObject obj, object value)
{
    obj.SetValue(SelectedTreeItemProperty, value);
}

// Using a DependencyProperty as the backing store for SelectedTreeItem.  This enables     animation, styling, binding, etc...
public static readonly DependencyProperty SelectedTreeItemProperty =
    DependencyProperty.RegisterAttached("SelectedTreeItem", typeof(object), typeof(YourVMClass), new PropertyMetadata(null, OnSelectedItemChange));

public static void OnSelectedItemChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    //do your stuff here eg.
    YourVMClass vm = d as YourVMClass;
    dynamic selectedItem = e.NewValue;
    vm.categoryName = selectedItem.Name;
    vm.categoryID = selectedItem.Tag.ToString();
    vm.categoryChosen = true;
}

您的XAML绑定如下

<TreeView vm:YourVMClass.SelectedTreeItem="{Binding SelectedItem,Mode=OneWay,RelativeSource={RelativeSource Self}}">

因此,这会将TreeView的Selected Item的值设置为VM类的SelectedTreeItem属性,并将触发change事件以便您执行进一步的操作。

另外我可以看到,目前您正在使用XML数据作为数据上下文,因此您可能需要根据您的使用情况调整上述代码,概念保持不变。如果您不打算更改数据上下文,则可以在相应XAML的代码隐藏文件中声明附加属性。但我建议你做一些重新分解,为你的XAML实现一个VM类,并将XML数据作为新VM中的属性公开。