从 TreeView 中获取所选项怎么办?

3
有人知道如何从TreeView中获取SelectedItem(而不是Header)吗? 以下是我的代码:
<TreeView Name="treeView1" DataContext="{Binding Path=PresentationsViewModel}" Grid.Column="1" >
    <TreeViewItem IsExpanded="True" Header="Objects-A-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListA}"></TreeViewItem>
    <TreeViewItem IsExpanded="True" Header="Objects-B-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListB}"></TreeViewItem>
    <TreeViewItem IsExpanded="True" Header="Objects-C-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListC}"></TreeViewItem>
</TreeView>

请注意,有3个不同的列表,包含3种不同的对象类型。如果能提供以下类似内容,将会对我很有帮助:
public Object SelectedObject
{
    set { _selectedObject = value; RunMyMethod(); RaisePropertyChanged("SelectedObject"); }
}  

你想做什么?为什么TreeView.SelectedItem对你无效? - Andy
4个回答

6

我知道这是一个旧问题并且可能已经过时,但像Charlie所说的那样。这也是可以在代码中使用的东西。例如,你可以这样做:

<ContentPresenter Content="{Binding ElementName=treeView1, Path=SelectedItem}" />

这将显示所选项目。您可以为其添加样式或DataTemplate,也可以使用默认的DataTemplate来显示您要显示的对象。


你的视图模型如何获取这些信息?我知道ContentPresenter保存了所选项目,但我们如何将其传递到视图模型中呢? - Bob Horn
1
@ Bob,我想你可以将TreeView中的SelectedItem绑定到ViewModel中的属性。然后,您还可以将此属性绑定到ContentPresenter或任何其他形式中以表示它。确保它具有INotify功能。因此,当您更改SelectedItem时,ViewModel和视图中的表示(如果您需要)都应该得到更新。 - Ingó Vals
1
如果它是只读的,这意味着您无法从ViewModel或其他地方设置它,除非用户在GUI中选择它。您仍然可以进行单向绑定并在另一个控件中显示它,或者在ViewModel中对其进行某些操作。也许我误解了您的意思。您想要实现什么? - Ingó Vals
我不想在视图模型中设置它。我只想让视图模型知道所选项是什么。 - Bob Horn
1
那么我相信您只需将适当类型的ViewModel属性绑定到TreeView中的SelectedItem属性即可。您可能需要将模式设置为OneWay或OneWayToSource(记不清是哪个了),但不确定。 - Ingó Vals
显示剩余2条评论

5

步骤1 安装NuGet:Install-Package System.Windows.Interactivity.WPF

步骤2 在您的窗口标签中添加:xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

步骤3 在TreeView中添加:

    <TreeView Name="treeView1" ... >
         <i:Interaction.Triggers>
              <i:EventTrigger EventName="SelectedItemChanged">
                   <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}" CommandParameter="{Binding ElementName=treeView1, Path=SelectedItem}"/>
              </i:EventTrigger>
          </i:Interaction.Triggers>
   ...
   </TreeView>

第四步:在你的ViewModel中添加:

        private ICommand _selectedItemChangedCommand;
        public ICommand SelectedItemChangedCommand
        {
            get
            {
                if (_selectedItemChangedCommand == null)
                    _selectedItemChangedCommand = new RelayCommand(args => SelectedItemChanged(args));
                return _selectedItemChangedCommand;
            }
        }

        private void SelectedItemChanged(object args)
        {
            //Cast your object
        }

谢谢您的解决方案 :) - Pentarex

3

迭戈·托雷斯的答案很简洁明了!但是对于那些不想为此目的安装NuGet包的人来说,您可以创建自己的依赖属性,当事件被触发时执行命令。

namespace View.Helper
{
    public class EventToCommandAdaptor
    {
        public static readonly DependencyProperty TreeViewSelectedItemChangedCommand_DpProp =
            DependencyProperty.RegisterAttached(
              "TreeViewSelectedItemChangedCommand",
              typeof(ICommand),
              typeof(EventToCommandAdaptor), // owner type
              new PropertyMetadata(new PropertyChangedCallback(AttachOrRemoveTreeViewSelectedItemChangedEvent))
              );

        public static ICommand GetTreeViewSelectedItemChangedCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(TreeViewSelectedItemChangedCommand_DpProp);
        }

        public static void SetTreeViewSelectedItemChangedCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(TreeViewSelectedItemChangedCommand_DpProp, value);
        }

        public static void AttachOrRemoveTreeViewSelectedItemChangedEvent(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            TreeView treeview = obj as TreeView;
            if (treeview != null)
            {
                ICommand cmd = (ICommand)args.NewValue;

                if (args.OldValue == null && args.NewValue != null)
                {
                    treeview.SelectedItemChanged += ExecuteTreeViewSelectedItemChanged;
                }
                else if (args.OldValue != null && args.NewValue == null)
                {
                    treeview.SelectedItemChanged -= ExecuteTreeViewSelectedItemChanged;
                }
            }
        }

        private static void ExecuteTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> args)
        {
            DependencyObject obj = sender as DependencyObject;
            ICommand cmd = (ICommand)obj.GetValue(TreeViewSelectedItemChangedCommand_DpProp);

            if (cmd != null)
            {
                if (cmd.CanExecute(args.NewValue))
                {
                    cmd.Execute(args.NewValue);
                }
            }
        }
    }
}

<Windows></Windows>中包含xmlns:vh="clr-namespace:View.Helper" TreeView的外观如下:
<TreeView ItemsSource="{Binding MyItemSource}"
    vh:EventToCommandAdaptor.TreeViewSelectedItemChangedCommand="{Binding MyCommand}">
</TreeView>

我在遇到类似情况时学会了这个技巧:我想在 DataGrid.MouseDoubleClick 事件触发时执行一个命令。但很抱歉我忘记标记来源了。

2
也许我误解了你的问题,但是,
treeView1.SelectedItem

应该可以正常工作。


3
很抱歉,TreeView没有这个功能(但是例如ListView有这个功能)。我正在尝试不使用任何Code-Behind来完成这个操作,只是通过< TreeView Name ="treeView1" DataContext =“ {Binding Path = PresentationsViewModel}” Grid.Column =“ 1” SelectedItem =“ {Binding Path = MySelectedObject}”>。 - Joseph jun. Melettukunnel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接