在的SelectedItem树视图(SelectedItem in TreeView)

2019-10-30 07:21发布

我想从我的TreeView选择的项目,但有一些问题。 我下面MVVM archetecture。 我的视图模型包含一个类,这是在我的模型的集合。 因此,我已绑定的TreeView的的ItemSource与该集合。 我想我的TreeView的selectedItem属性绑定到绑定的集合的一个项目。 我怎么做。 下面是的SelectedItem和IsSelected属性的代码。

    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; “这个”指针包含到我的TreeView的是绑定的集合。 我需要有一个SelectedDataSource,这样我可以把它分配给选定的项目。 我怎样才能让我的树视图返回我selectedItem属性的集合?

据透露,这是我的TreeView XAML代码

<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。

任何帮助都感激不尽。

谢谢

Answer 1:

而且对你的问题的评论文章,对WPF的TreeView给人以MVVM开发一些独特的挑战,并且在这些之中是检测当前选定的项目。 为此,您可以使用附加的行为。 首先,写一个静态类包含的行为...

   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 ...

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

这种“线”的电视行为一个ICommand在你的虚拟机。 最后,声明中的ICommand你的虚拟机...

公众的ICommand SelectedItemCommand {获得; 组; }

并初始化它...

 SelectedItemCommand = new RelayCommand(ExecuteSelectedItemCommand, 
                                         CanExecuteSelectedItemCommand);

然后实现您的代表...

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

当用户选择一个电视项目,你的“执行”代表将获得该项目的包装实例,可以拆箱并等等等等等等。

请注意,在这个例子中,附加的行为假设电视机的寿命是一样的应用程序,否则你必须在无线化附加的行为。 它还假定电视的ItemsSource绑定到一些明智的。

这将解决让电视的SelectedItem的问题,而其余MVVM兼容的(如果这样的事情作为MVVM兼容的存在)。

我使用的继电器Command类是从MSDN中的链接文章服用。 作为参考,在这里它是...

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链接,以获取有关此类的详细信息。



文章来源: SelectedItem in TreeView