树视图中的选定项 [英] SelectedItem in TreeView

查看:25
本文介绍了树视图中的选定项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 TreeView 中获取所选项目,但遇到了一些问题.

I am trying to get the selected item from my TreeView but having some problem.

我正在遵循 MVVM 架构.我的 ViewModel 包含一个在我的模型中的类的集合.所以我已将 TreeView 的 ItemSource 与该集合绑定.我想将我的 TreeView 的 selectedItem 绑定到绑定集合的一个项目.我怎么做?这是 SelectedItem 和 IsSelected 属性的代码.

I am following MVVM archetecture. My ViewModel contains a collection of a class which is in my Model. So I have binded the ItemSource of TreeView with that collection. I want to bind the selectedItem of my TreeView to an item of the binded collection. How do I do that? Here is the code for SelectedItem and IsSelected Property.

    private static sourceData _selectedItem = null;
    /// <summary>
    /// Selected Item in the tree
    /// </summary>
    public static sourceData SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (_selectedItem != value)
            {
                _selectedItem = value;
            }
        }
    }

    private bool _isSelected;
    /// <summary>
    /// Get/Set for Selected node
    /// </summary>
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (_isSelected != value)
            {
                _isSelected = value;

                if (_isSelected)
                {
                    SelectedItem = this;
                    OnPropertyChanged("IsSelected");
                }
            }
        }
    }

    /// <summary>
    /// Property changed event
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Property changed event handler
    /// </summary>
    /// <param name="propertyName"></param>
    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

当我调试这个时, int SelectedItem = this; 'this' 指针包含我的树视图绑定到的集合.我需要有一个 SelectedDataSource 以便我可以将它分配给选定的项目.如何让我的 TreeView 返回集合中的 selectedItem?

When I debug this, int SelectedItem = this; 'this' pointer contains the collection to which my treeview is binded. I needed to have a SelectedDataSource so that I could assign it to the selected Item. How can I make my TreeView return me the selectedItem in the collection??

仅供参考,这是我用于 TreeView 的 XAML 代码

FYi, this is my XAML code for TreeView

<TreeView Margin="5,0,0,0" ItemsSource="{Binding SourceData}"  Width="390">
                    <TreeView.ItemContainerStyle>
                        <Style TargetType="{x:Type TreeViewItem}">
                            <Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
                          <Setter Property="ContextMenu">
                                <Setter.Value>
                                    <ContextMenu Name="contextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" >
                                        <MenuItem Name="menuItem" Header="Rename" Command="{Binding RenameCommand}" />
                                    </ContextMenu>
                                </Setter.Value>
                            </Setter>
                            <Style.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TreeView.ItemContainerStyle>

PS:如果我在我的模型中编写上面的代码,我会一切正常.但是我不能在模型中编写上面的代码,它必须在VM中.

PS: If I write the above code in my Model, I get everything working perfectly fine. But I can not write the above code in Model, it has to be in VM.

推荐答案

对于您的问题的进一步评论,WPF TreeView 为 MVVM 开发人员提供了一些独特的挑战,其中包括检测当前选定的项目.为此,您可以使用附加行为.首先,编写一个静态类来包含行为...

Further to the commentary on your question, the WPF TreeView gives some unique challenges to the MVVM developer, and among these is detecting the currently selected item. For this you can use attached behaviour. To begin, write a static class to contain the behaviour...

   public static class TvBehaviour
    {
        #region TvSelectedItemChangedBehaviour (Attached DependencyProperty)
        public static readonly DependencyProperty TvSelectedItemChangedBehaviourProperty =
            DependencyProperty.RegisterAttached("TvSelectedItemChangedBehaviour",
                                                typeof (ICommand),
                                                typeof (TvBehaviour),
                                                new PropertyMetadata(
                                                    OnTvSelectedItemChangedBehaviourChanged));

        public static void SetTvSelectedItemChangedBehaviour(DependencyObject o, ICommand value)
        {
            o.SetValue(TvSelectedItemChangedBehaviourProperty, value);
        }
        public static ICommand GetTvSelectedItemChangedBehaviour(DependencyObject o)
        {
            return (ICommand) o.GetValue(TvSelectedItemChangedBehaviourProperty);
        }
        private static void OnTvSelectedItemChangedBehaviourChanged(DependencyObject d,
                                                                    DependencyPropertyChangedEventArgs e)
        {
            TreeView tv = d as TreeView;
            if (tv != null)
            {
                tv.SelectedItemChanged += (s, a) =>
                    {
                        GetTvSelectedItemChangedBehaviour(tv).Execute(a.NewValue);
                        a.Handled = true;
                    };
            }
        }
        #endregion

}

然后将类的命名空间导入您的 Xaml(使用 xmlns).然后你可以沿着这些线声明一个 TreeView...

Then import the class's namespace into your Xaml (using xmlns). You can then declare a TreeView along these lines...

    <TreeView ItemsSource="{Binding MyList}" 
              ItemTemplate="{StaticResource My_data_template}"
              tvBinding:TvBehaviour.TvSelectedItemChangedBehaviour="{Binding             
                           SelectedItemCommand}"
              SelectedValuePath="Name"
              >
    </TreeView>

这会将电视行为连接"到 VM 中的 ICommand.最后,在您的 VM 中声明 ICommand...

This 'wires' the TV behaviour to an ICommand in your VM. Finally, declare the ICommand in your VM...

public ICommand SelectedItemCommand { get;放;}

public ICommand SelectedItemCommand { get; set; }

并初始化它...

 SelectedItemCommand = new RelayCommand(ExecuteSelectedItemCommand, 
                                         CanExecuteSelectedItemCommand);

然后实现您的委托...

And then implement your delegates...

    private void ExecuteSelectedItemCommand(object obj)
    {
        // downcast 'obj' to get the instance of the selected item
    }
    private bool CanExecuteSelectedItemCommand(object obj)
    {
        return true;
    }

当用户选择一个 TV 项目时,您的执行"委托将获得该项目的一个装箱实例,您可以将其取消装箱等等.

When the user selects a TV item, your 'execute' delegate will get a boxed instance of the item, and you can unbox it and etc etc etc.

请注意,此示例中的附加行为假设电视的生命周期与应用程序相同,否则您必须取消附加行为.它还假设 TV ItemsSource 绑定到一些合理的东西.

Note that the attached behaviour in this example assumes that the TV's lifetime is the same as the app, otherwise you have to unwire the attached behaviour. It also assumes that the TV ItemsSource is binding to something sensible.

这将解决在保持 MVVM 兼容的同时获取 TV SelectedItem 的问题(如果存在 MVVM 兼容这样的东西).

That will solve the problem of getting the TV SelectedItem while remaining MVVM compliant (if such a thing as MVVM compliant exists).

我使用的中继命令类取自 MSDN 中的链接文章.仅供参考,这里是...

The Relay Command class I used was taken from the linked article in MSDN. For reference purposes, here it is...

public class RelayCommand : ICommand
{   //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    private readonly Action<object> _execute;
    private readonly Predicate<object> _canExecute;
}

使用上面的 MSDN 链接获取有关此类的更多信息.

Use the MSDN link above to get more info about this class.

这篇关于树视图中的选定项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆