Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

INotifyPropertyChanged in subclass

I want to bind a TextBox in the window to a property contained within a class that is a variable of the viewmodel and ensure that INotifyPropertyChanged's PropertyChanged event propagates from the class to the parent.

Let me illustrate with an example:

(Window's DataContext is set to an instance of ViewModel)

public class ViewModel {
    private OtherClass classInstance = new OtherClass();

    public int Attribute {
        get { return classInstance.Attribute; }
    }
}

public class OtherClass : INotifyPropertyChanged {
    private int _attribute;
    public int Attribute {
        get { return _attribute; }
        set { 
            _attribute = value;
            PropertyChanged("Attribute");
        }
    }
    ...
}

The problem in this example is that, when Attribute changes, the bound Textbox does not update the binding since I assume it's listening to the ViewModel's PropertyChanged event and not that of the instance of OtherClass.

Any ideas on how to remedy this situation? I was thinking about chaining OtherClass's INotifyPropertyChanged to that of its parent, but there has to be a better way.

like image 696
aleph_null Avatar asked Sep 27 '11 20:09

aleph_null


People also ask

What is the purpose of INotifyPropertyChanged?

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed. For example, consider a Person object with a property called FirstName .

How do you implement INotifyPropertyChanged?

To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.

What is INotifyPropertyChanged in xamarin forms?

The PropertyChanged event notifies the UI that a property in the binding source (usually the ViewModel) has changed. It allows the UI to update accordingly. The interface exists for WPF, Silverlight, UWP, Uno Platform, and Xamarin.


1 Answers

Why not bind directly to the class property instead of using a proxy?

public class ViewModel {
    private OtherClass classInstance = new OtherClass();

    public OtherClass MyOtherClass {
        get { return classInstance; }
    }
}

Then in your binding you can simply reference the property via the SubClass

{Binding MyOtherClass.Attribute}

A drop dead simple example, but it works!

The Code Behind:

public partial class MainWindow : Window {
   private readonly SomeClass _someClass = new SomeClass();

   public MainWindow() {
      InitializeComponent();
      DataContext = _someClass;
   }
}

public class SomeClass: INotifyPropertyChanged {      
   private readonly SomeSubClass _mySubClass = new SomeSubClass();

   public SomeSubClass MySubClass {
      get { return _mySubClass; }
   }

   private String _name;
   public String Name {
      get { return _name; }
      set {
         _name = value;
         OnPropertyChanged("Name");
      }
   }

   //Property Change Stuff
}

public class SomeSubClass : INotifyPropertyChanged {
   private String _name;
   public String Name {
      get {
         return _name;
      }
      set {
         _name = value;
         OnPropertyChanged("Name");
      }
   }

   //Property Change Stuff
}

The XAML:

<Window x:Class="JWC.Examples.WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow">
    <StackPanel>
        <Label Content="Name" VerticalAlignment="Top" />
        <TextBox Text="{Binding Name}" />
        <Label Content="SubClass.Name" />
        <TextBox Text="{Binding MySubClass.Name}" />
        <Label Content="Bound to Name" />
        <TextBlock Text="{Binding Name}" />
        <Label Content="Bound to MySubClass.Name" />
        <TextBlock Text="{Binding MySubClass.Name}" />
    </StackPanel>
</Window>
like image 150
Josh Avatar answered Sep 27 '22 18:09

Josh