2

Found so many answers in here but none worked for me. here is my 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 usercontrol in my mainwindow. Whenever any codebook adds there, i am going to send that information to this treeviewmodel via mediator class. Based on that it will update its data. Able to add nodes up to 3 levels without any issues.

When i am debugging, selecting any item in treeview, the treeviewitem is getting bold but IsSelected property 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.

Thanks Rani

Pragmateek
  • 13,174
  • 9
  • 74
  • 108
Rani
  • 75
  • 1
  • 2
  • 6

1 Answers1

1

You have a number of problems with your code. Using a Binding like this will cause an error because you are looking for the IsSelected property in the object that is set as the DataContext for the TreeViewItem and not in the view model:

<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 really want to data bind to the TreeViewItem.IsSelected property to your view model, then you could try using a RelativeSource Binding instead:

<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 IsSelected in the object that is data bound to the view/UserControl DataContext property... I am assuming that that will be your view model. I can't confirm whether this will actually work though... enter your next problem.

The TreeViewItem.IsSelected property 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 TreeView can 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 MVVM and WPF MVVM TreeView SelectedItem questions here on Stack Overflow for more information on data binding like this.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Thanks Sheridan, It worked for me.I used Viewmodel for each TreeViewItem. Yet to add code for getting the selected item value. (CodeBook, DocSet or Field). Thanks a ton. – Rani Mar 21 '14 at 13:03