0
votes

I have created A treeView named ValueTreeView in xaml code it uses the datatemplate created in the following code,that binds entirely to a generic class ValueHolder

This is the class used for binding

public class ValueHolder
{
    public string VHName{ get; set; }
    public string VHValue{ get; set; }
}

This is the user control having the treeview

  public partial class UserControl1 : UserControl
  {
     ObservableCollection<ValueHolder> source;

     public UserControl1()
     {

        InitializeComponent();

        source= new ObservableCollection<ValueHolder>();

        //Data Template for the treeView

        DataTemplate cardLayout = new DataTemplate();
        cardLayout.DataType = typeof(ValueHolder);

        FrameworkElementFactory ValueStack= new FrameworkElementFactory(typeof(StackPanel));
        ValueStack.Name = "Details";
        ValueStack.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

        FrameworkElementFactory VName= new FrameworkElementFactory(typeof(TextBlock));
        VName.SetBinding(TextBlock.TextProperty, new Binding("VHName"));
        ValueStack.AppendChild(VName);

        FrameworkElementFactory Space = new FrameworkElementFactory(typeof(TextBlock));
        Space.SetValue(TextBlock.WidthProperty, 10.0);
        ValueStack.AppendChild(Space);

        FrameworkElementFactory VValue= new FrameworkElementFactory(typeof(TextBlock));
        VValue.SetBinding(TextBlock.TextProperty, new Binding("VHValue"));
        ValueStack.AppendChild(VValue);

        cardLayout.VisualTree = ValueStack;

        ValueTreeView.ItemTemplate = cardLayout;

        //Initializing the TreeViewItems

        ValueHolder vh1 = new ValueHolder() { VHName = "VH1", VHValue = "456"};
        ValueHolder vh2 = new ValueHolder() { VHName = "VH2", VHValue = "578"};
        ValueHolder vh3 = new ValueHolder() { VHName = "VH3", VHValue = "235"};

        source.Add(vh1);
        source.Add(vh2);
        source.Add(vh3);

        ValueTreeView.ItemsSource = source;

    }

The below is the event handler called when the selection item changed

    private void ValueTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    { 
        var s=((ValueHolder)((TreeView)sender).SelectedItem);
        if(s.VHName=="VH2")
            s.VHValue = "111";
    }
}

The two text blocks in each TreeViewItem are bound to the two class variables.

My problem is when I change the Value of the Class property,it is not reflected in the UI,even though I use ObservableCollection for the Item source of the TreeView.

The event handler changes the VHValue property of the class and it is getting changed in the backend,yet not reflected in the UI

My xaml code:

   <UserControl x:Class="Checker.UserControl1"
         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" 
         d:DesignHeight="300" d:DesignWidth="300">
  <Grid>
  <TreeView x:Name="ValueTreeView" SelectedItemChanged="ValueTreeView_SelectedItemChanged">           
  </TreeView>
  </Grid>
  </UserControl>
1

1 Answers

1
votes

ObservableCollection works only for collection changes not the changes of items in collection. You need to implement INotifyPropertyChanged interface for ValueHolder class more details here

  public class ValueHolder : INotifyPropertyChanged
  {
      private string _VHName;
      private string _VHValue;
      // Declare the event 
      public event PropertyChangedEventHandler PropertyChanged;

      public string VHName
      {
          get { return _VHName; }
          set
          {
              _VHName = value;
              // Call OnPropertyChanged whenever the property is updated
              OnPropertyChanged("VHName");
          }
      }

      public string VHValue
      {
          get { return _VHValue; }
          set
          {
              _VHValue= value;
              // Call OnPropertyChanged whenever the property is updated
              OnPropertyChanged("VHValue");
          }
      }

      // Create the OnPropertyChanged method to raise the event 
      protected void OnPropertyChanged(string name)
      {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
              handler(this, new PropertyChangedEventArgs(name));
          }
      }
  }
}