【问题标题】:How do I extract SelectedItem from a TreeView when using data binding?使用数据绑定时如何从 TreeView 中提取 SelectedItem?
【发布时间】:2013-04-14 16:17:28
【问题描述】:

我已按照本文的建议将树视图控件绑定到 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 { }
    }

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

【问题讨论】:

  • 我在这里问了同样的问题:stackoverflow.com/a/9143193/279516。我最终没有使用答案,因为它很复杂。我作弊并使用了代码隐藏文件。希望这会有所帮助。
  • 您是如何使用代码隐藏文件的?您的意思是您以编程方式填充树视图而不是使用绑定?
  • “这似乎不像我想象的那样工作。”你可以再详细一点吗?它表现如何?
  • 这是我对那个问题/链接的评论:我刚刚又看了一遍代码,看来我作弊了。我在树视图控件中有这个:SelectedItemChanged="TreeView_SelectedItemChanged"。在xaml.cs中,我设置了选中项:((ApplicationServerViewModel)DataContext).SelectedApplicationServer = e.NewValue as ApplicationServer;

标签: c# wpf xml treeview


【解决方案1】:

您可能应该摆脱肮脏的 try catch em all。您可以使用 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
        }
    }  
}

【讨论】:

    【解决方案2】:

    在使用 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 中的属性。

    【讨论】:

      猜你喜欢
      • 2011-09-12
      • 2015-05-15
      • 2010-11-17
      • 2013-02-22
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多