wpf 无法将 TreeViewItem 的 IsSelected 属性绑定到 ViewModel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22532500/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:17:08  来源:igfitidea点击:

Unable to bind IsSelected property of TreeViewItem to ViewModel

c#wpfmvvm

提问by Rani

Found so many answers in here but none worked for me. here is my XAML

在这里找到了很多答案,但没有一个对我有用。这是我的 XAML

<UserControl x:Class="Helper.View.TreeViewUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             xmlns:this="clr-namespace:Helper.Model"
             xmlns:vm="clr-namespace:Helper.ViewModel"
              DataContext="{DynamicResource TreeNodeViewModel}">
    <UserControl.Resources>
        <vm:TreeNodeViewModel x:Key="TreeNodeViewModel"/>
    </UserControl.Resources>
    <Grid>
        <TreeView ItemsSource="{Binding CodeBookEnties}" >
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                    <Setter Property="FontWeight" Value="Normal" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.Resources>
                <HierarchicalDataTemplate ItemsSource="{Binding DocSetCollection}" DataType="{x:Type this:CodeBookEntity}">
                    <Label Content="{Binding CodeBookName}"/>
                </HierarchicalDataTemplate>

                <HierarchicalDataTemplate ItemsSource="{Binding FieldCollection}" DataType="{x:Type this:DocumentEntity}">
                    <Label Content="{Binding DocSetName}"/>
                </HierarchicalDataTemplate>

                <DataTemplate DataType="{x:Type this:FieldEntity}">
                    <Label Content="{Binding FieldName}"/>
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</UserControl>

and my viewmodel class goes like this:

我的视图模型类是这样的:

namespace Helper.ViewModel
{
    public class TreeNodeViewModel : ViewModelBase
    {
        private ObservableCollection<DocumentEntity> children;
        private CodeBookEntity _codeBookEntity;
        private ObservableCollection<CodeBookEntity> codeBookEntities;
        //TreeNodeViewModel _parent = null;
        bool _isExpanded = false;
        bool _isSelected = false;


        public TreeNodeViewModel()
        {
            Mediator.Instance.Register(
                   //Callback delegate, when message is seen
                   (Object o) =>
                   {
                       ParentNode = (CodeBookEntity)o;
                   }, ViewModelMessages.CodeBookCreated);          
        }

        public override string ToString() {
            return _codeBookEntity.CodeBookName;
        }

        public ObservableCollection<DocumentEntity> Children
        {
            get { return CodeBookEnties[0].DocSetCollection; }

            set {

                CodeBookEnties[0].DocSetCollection = value;

                //OnPropertyChanged("CodeBookEnties");
            }
        }

        public CodeBookEntity ParentNode 
        {
            get { return _codeBookEntity; }

            set { 
                _codeBookEntity = value;
                if (CodeBookEnties == null)
                {
                    CodeBookEnties = new ObservableCollection<CodeBookEntity>();
                }


                CodeBookEnties.Add(_codeBookEntity);   

                OnPropertyChanged("ParentNode");
            }
        }
        public string Name {
            get { return _codeBookEntity.CodeBookName; }
        }

        public string Description 
        { get { return _codeBookEntity.CodeBookDescription; } }

        #region Presentation Members

        #region IsExpanded

        /// <summary>
        /// Gets/sets whether the TreeViewItem 
        /// </summary>
        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (value != _isExpanded)
                {
                    _isExpanded = value;
                    this.OnPropertyChanged("IsExpanded");
                }

                // Expand all the way up to the root.
                //if (_isExpanded && _parent != null)
                //    _parent.IsExpanded = true;
            }
        }

        #endregion // IsExpanded

        #region IsSelected

        /// <summary>
        /// Gets/sets whether the TreeViewItem 
        /// associated with this object is selected.
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value != _isSelected)
                {
                    _isSelected = value;
                    this.OnPropertyChanged("IsSelected");
                }
            }
        }

        #endregion // IsSelected

        #region NameContainsText

        public bool NameContainsText(string text)
        {
            if (String.IsNullOrEmpty(text) || String.IsNullOrEmpty(this.Name))
                return false;

            return this.Name.IndexOf(text, StringComparison.InvariantCultureIgnoreCase) > -1;
        }

        #endregion // NameContainsText

        #endregion // Presentation Members    

        public bool IsLeaf {
            get { return !Children.Any(); }
        }

        public ObservableCollection<CodeBookEntity> CodeBookEnties
        {
            get
            {
                return codeBookEntities;
            }
            set
            {
                if (codeBookEntities == null)
                {
                    codeBookEntities = new ObservableCollection<CodeBookEntity>();
                }
                codeBookEntities = value;
                OnPropertyChanged("CodeBookEnties");
            }
        }
    }
}

I used this usercontrolin my mainwindow. Whenever any codebook adds there, i am going to send that information to this treeviewmodelvia mediator class. Based on that it will update its data. Able to add nodes up to 3 levels without any issues.

usercontrol在我的mainwindow. 每当有任何代码本添加到那里时,我都会treeviewmodel通过中介类将这些信息发送给它。基于此,它将更新其数据。能够添加最多 3 个级别的节点而不会出现任何问题。

When i am debugging, selecting any item in treeview, the treeviewitemis getting bold but IsSelectedproperty is not getting hit. I have to get its class based on its selection (CodeBook, Document, Field are the hierarchy of classes here) whenever i select an element so that i can process that element later.
Not sure what is the error. Please help me.

当我调试时,在 中选择任何项目时treeviewtreeviewitem它变得粗体,但IsSelected属性没有受到影响。每当我选择一个元素时,我都必须根据它的选择来获取它的类(CodeBook、Document、Field 是这里的类的层次结构),以便我以后可以处理该元素。
不知道是什么错误。请帮我。

Thanks Rani

谢谢拉尼

采纳答案by Sheridan

You have a number of problems with your code. Using a Bindinglike this will cause an error because you are looking for the IsSelectedproperty in the object that is set as the DataContextfor the TreeViewItemand notin the view model:

您的代码有很多问题。使用Binding这样的,因为你正在寻找的会导致错误IsSelected被设置为在对象属性DataContextTreeViewItem,并没有在视图模式:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    <Setter Property="FontWeight" Value="Normal" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="FontWeight" Value="Bold" />
        </Trigger>
    </Style.Triggers>
</Style>

If you reallywant to data bind to the TreeViewItem.IsSelectedproperty to your view model, then you could try using a RelativeSource Bindinginstead:

如果您真的想将数据绑定到TreeViewItem.IsSelected视图模型的属性,那么您可以尝试使用 aRelativeSource Binding代替:

<Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, RelativeSource={
    RelativeSource AncestorType={x:Type YourPrefix:YourView}}, Mode=TwoWay}" />

Note that this will search for a property named IsSelectedin the object that is data bound to the view/UserControl DataContextproperty... I am assuming that that will be your view model. I can't confirm whether this will actuallywork though... enter your next problem.

请注意,这将搜索IsSelected在数据绑定到视图/UserControl DataContext属性的对象中命名的属性......我假设这将是您的视图模型。我无法确认这是否真的有效...输入您的下一个问题。

The TreeViewItem.IsSelectedproperty is usually data bound to a property of the data object that is data bound to the TreeViewItem. Apart from any other reason, this is usually done because a TreeViewcan have many TreeViewItems that are selected and your one property in the view model cannot reference them all. Please see the Get Selected TreeViewItem Using MVVMand WPF MVVM TreeView SelectedItemquestions here on Stack Overflow for more information on data binding like this.

TreeViewItem.IsSelected属性通常是绑定到数据对象TreeViewItem的属性的数据,该属性是数据绑定到. 除了任何其他原因,这通常是因为 aTreeView可以有许多TreeViewItem被选中的 s 并且您在视图模型中的一个属性不能全部引用它们。有关此类数据绑定的更多信息,请参阅Stack Overflow 上的Get Selected TreeViewItem Using MVVMWPF MVVM TreeView SelectedItem问题。