propertychangedeventargs onpropertychanged ejemplo wpf data-binding inotifypropertychanged

wpf - onpropertychanged - INotifyPropertyChanged en la subclase



propertychangedeventargs (4)

¿Por qué no enlazar directamente a la propiedad de la clase en lugar de usar un proxy?

public class ViewModel { private OtherClass classInstance = new OtherClass(); public OtherClass MyOtherClass { get { return classInstance; } } }

Luego, en su enlace, simplemente puede hacer referencia a la propiedad a través de la Subclase

{Binding MyOtherClass.Attribute}

Un ejemplo simple, ¡pero funciona!

El código detrás:

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 }

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

Quiero vincular un TextBox en la ventana a una propiedad contenida dentro de una clase que sea una variable del modelo de vista y asegurarme de que el evento PropertyChanged de INotifyPropertyChanged se propague desde la clase al padre.

Déjame ilustrar con un ejemplo:

(Window''s DataContext está configurado a una instancia de 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"); } } ... }

El problema en este ejemplo es que, cuando el atributo cambia, el cuadro de texto encuadernado no actualiza el enlace, ya que supongo que está escuchando el evento PropertyChanged de ViewModel y no el de la instancia de OtherClass.

¿Alguna idea sobre cómo remediar esta situación? Estaba pensando en encadenar INotifyPropertyChanged de OtherClass al de su principal, pero tiene que haber una forma mejor.


Creo que la clase padre debe suscribirse al evento childCahnged child ... algo como:

public class ViewModel { private OtherClass classInstance = new OtherClass(); public ViewModel() { classInstance.PropertyChanged += NotifyChildAttributeChanged; } public int Attribute { get { return classInstance.Attribute; } } }

NotifyChildAttributeChanged es básicamente un método que solo escucha la propiedad "Attribute" y dispara una notificación PropertyChanged propia.

Por supuesto, nuestra clase padre debe implementar INotifyPropertyChanged, así como todos los modelos de vista (preferiblemente) y su DataContext detectará el cambio.


Deberás hacer algo como esto:

public class ViewModel { public ViewModel() { classInstance = new OtherClass(); classInstance.PropertyChanged += HandleAttributeChanged; } private void HandleAttributeChanged(object Sender, NotifyPropertyChangedEventArgs args) { PropertyChanged("Attribute"); } }

No lo muestro aquí, pero también debe implementar IDisposable y darse de baja del evento PropertyChanged en su hijo, de lo contrario, perderá memoria.

Alternativamente, puede exponer classInstance como una propiedad pública y establecer su enlace a: ViewModel.classInstance . Tenga en cuenta que debe ser una propiedad y no el campo en sí.