【问题标题】:Selected TreeViewItem is null选定的 TreeViewItem 为空
【发布时间】:2013-07-09 09:34:13
【问题描述】:

我想为我的 TreeView 创建一个 ContextMenu。树视图 XAML:

<helper:ExtendedTreeView Grid.Row="5" ItemsSource="{Binding OCFrage, Mode=TwoWay}" SelectedItem_="{Binding SelectedItem, Mode=TwoWay}" SelectedItemChanged="treeView1_SelectedItemChanged" x:Name="treeView1" Height="205" Width="215">
    <helper:ExtendedTreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:T_Frage}" ItemsSource="{Binding Wertung, Mode=TwoWay}">
            <TextBlock Text="{Binding Text}"/>
        </HierarchicalDataTemplate>
    </helper:ExtendedTreeView.Resources>
</helper:ExtendedTreeView>

而 helper:ExtendedTreeView 是这个类:

public class ExtendedTreeView : TreeView
{
    public ExtendedTreeView()
        : base()
    {
        this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(self);
    }

    void self(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (SelectedItem != null)
        {
            SetValue(SelectedItem_Property, SelectedItem);
        }
    }

    public object SelectedItem_
    {
        get { return (object)GetValue(SelectedItem_Property); }
        set { SetValue(SelectedItem_Property, value); }
    }
    public static readonly DependencyProperty SelectedItem_Property = DependencyProperty.Register("SelectedItem_", typeof(object), typeof(ExtendedTreeView), new UIPropertyMetadata(null));
}

我正在使用它来绑定 SelectedItem 并在我的 ViewModel 中使用它。

我的 TreeView 有 T_Frage 类型的“标题”,它们的节点是 T_Wertung 类型,所以它会是

  • T_Frage
    • T_Wertung
    • T_Wertung
  • T_Frage
    • T_Wertung ...

我想为标题创建一个 ContextMenu。因此,如果用户单击 T_Frage 类型的 TreeViewItem,则会弹出一个 ContextMenu。我已经按照本指南http://canhandre.wordpress.com/2012/01/14/wpf-treeview-with-contextmenu/ 进行操作,我目前正在 CodeBehind 中进行测试,只是为了对其进行测试。问题是当这段代码被执行时:TreeViewItem selectedItem = treeView1.SelectedItem as TreeViewItem;treeView1.SelectedItem 的类型是 T_Frage 并且有它的值,但是当我分配给 selectedItem 时,selectedItem 仍然为空......为什么?

编辑:删除 ItemsSource 并在 XAML 中创建普通 TreeViewItems

  <TreeViewItem Header="Edit" Name="Edit">
       <TreeViewItem Header="Text"/>
       <TreeViewItem Header="Image"/>
       <TreeViewItem Header="Table"/>
  </TreeViewItem>

将在此处分配值TreeViewItem selectedItem = treeView1.SelectedItem as TreeViewItem;。这意味着我无法将 TreeView 中的 T_Frage 类型的项目分配给 TreeViewItem 类型的变量。我应该如何为我的 TreeView 中不是 TreeViewItem 类型的项目创建 ContextMenu?如您在上面看到的,将 T_Frage 的类型分配给 TreeViewItem 将导致 null。

【问题讨论】:

  • 那么,在执行赋值步骤之前,treeView1.SelectedItem 是一个对象,但赋值之后selectedItem 是null,对吗? treeView1.SelectedItem 赋值后呢,还是对象吗?
  • @Treb 是的。 treeView1.SelectedItem 保持不变,treeView1 是 Helper.ExtendedTreeView 类型。如果我尝试这样做:TreeViewItem selectedItem = (TreeViewItem)treeView1.SelectedItem; 它会显示 InvalidCastException,因为 treeView1.SelectedItem 是 T_Frage 类型。我只想在右键单击此项目时为其创建一个 ContextMenu,但我无法为不是 TreeViewItem 类型的项目创建一个 ContextMenu(据我所知..)。我也试过Helper.ExtendedTreeView selectedItem = treeView1.SelectedItem as Helper.ExtendedTreeView; ,仍然为空。
  • 好吧,我将 treeView1.SelectedItem 作为对象类型。我已经用你的方法尝试过了,然后将对象分配给 TreeViewItem,但它仍然为空,或者当我尝试将对象强制转换为 TreeViewItem 类型时,它又是 InvalidCastException。这样做object selectedItem = (object)treeView1.SelectedItem 然后TreeViewItem twv = (TreeViewItem)selectedItem; 将不起作用。
  • 毫不奇怪,如果TreeViewItem 的演员表在treeView1.SelectedItem 上不起作用,它也不会在selectedItem 上起作用。你能提供更多代码,关于你想用selectedItem做什么 - 你如何使用它来创建上下文菜单?

标签: c# wpf treeview contextmenu selecteditem


【解决方案1】:

我知道它现在是 MVVM 而不是 CodeBehind,但我只是想先在 CodeBehind 中对其进行测试,然后在 MVVM 中进行所有操作,因为我认为立即在 MVVM 中进行操作会更难……无论如何,这是我想要什么:

<helper:ExtendedTreeView Grid.Row="5" ItemsSource="{Binding OCFrage, Mode=TwoWay}" SelectedItem_="{Binding SelectedItem, Mode=TwoWay}" SelectedItemChanged="treeView1_SelectedItemChanged" x:Name="treeView1" Height="205" Width="215">
    <TreeView.ContextMenu>
        <ContextMenu ItemsSource="{Binding OCContext}"/>
    </TreeView.ContextMenu)
    <helper:ExtendedTreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:T_Frage}" ItemsSource="{Binding Wertung, Mode=TwoWay}">
            <TextBlock Text="{Binding Text}"/>
        </HierarchicalDataTemplate>
    </helper:ExtendedTreeView.Resources>
</helper:ExtendedTreeView>

视图模型:

private object _selecteditem;
public object SelectedItem
{
    get { return _selecteditem; }
    set
    {
        OCContext = new ObservableCollection<T_Wertung>();
        if (value is T_Frage)
        {
            T_Frage selected = (T_Frage)value;
    //do something with selected
    OCContext.Add(new T_Wertung(1,"Test",100));
            }
        }
        RaisePropertyChanged(() => SelectedItem);
    }
}

private ObservableCollection<T_Wertung> _occontext;
public ObservableCollection<T_Wertung> OCContext
{
    get
    {
        if (_occontext == null)
            _occontext = new ObservableCollection<T_Wertung>();
        return _occontext;
    }
    set
    {
        _occontext = value;
        RaisePropertyChanged(() => OCContext);
    }
}

由于我绑定到 TreeView 的 SelectedItem,我可以询问 SelectedItem 是否属于 T_Frage 类型。如果是真的,我将创建一个 T_Frage 类型的新变量并将其上下文设置为 SelectedItem 的值。现在我可以对这个项目做一些事情,然后将一个项目添加到名为OCContext 的 ContextMenu 的列表中。当我右键单击该项目时,会弹出 ContextMenu 并显示 OCContext 的项目。

【讨论】:

  • 我的 XAML 知识接近于零,但这在我看来过于复杂。很抱歉,但我唯一的建议是回到您在问题中链接的简单示例。完全像那样实现它(例如,不从TreeView派生你自己的类),让它尽可能简单。一旦你让它工作,你可以扩展它。
猜你喜欢
  • 1970-01-01
  • 2013-09-27
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多