2011-09-27 14 views
7

Quiero vincular un TextBox en la ventana a una propiedad contenida dentro de una clase que es una variable del viewmodel y asegurar que el evento PropertyChanged de INotifyPropertyChanged se propague desde la clase al padre.INotifyPropertyChanged en la subclase

Permítanme ilustrar con un ejemplo:

(DataContext de ventana se establece en una instancia de modelo de vista)

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 los cambios de atributo, el bound Textbox 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.

Respuesta

6

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

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

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

Luego, en su unión sólo tiene que hacer referencia a la propiedad a través de la subclase

{Binding MyOtherClass.Attribute} 

Una gota ejemplo sencillo muerto, pero funciona!

el código subyacente:

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> 
+0

Los ejemplos simples Drop Dead son el mejor tipo de ejemplos :) – Moulde

+0

Esto no es práctico si SomeSubClass contiene un montón de propiedades. ¿Realmente vas a duplicar todas esas propiedades? – Sean

+0

@Sean - No estoy seguro de lo que quiere decir con "duplicar todas esas propiedades". En el ejemplo, es solo una coincidencia que Name esté definido en el padre y el hijo. No hace ninguna diferencia a la pregunta subyacente. Principalmente, puede vincular directamente a las propiedades de la clase secundaria en lugar de tratar de usar variables proxy. En ese sentido, no habría duplicación. – Josh

0

creo que la clase padre debe suscribirse al niño propertyCahnged event..something 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 sólo escucha a la propiedad "Atributo" y despide una notificación de PropertyChanged su propio ...

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

4

Usted tendrá que 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 me presento aquí, pero también se debe aplicar IDisposable y darse de baja del evento PropertyChanged de su hijo, de lo contrario se perderá memoria.

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

+0

funciona para mí cambiar NotifyPropertyChangedEventArgs para PropertyChangedEventArgs. –

Cuestiones relacionadas