2011-09-27 6 views
7

Chcę powiązać TextBox w oknie z właściwością zawartą w klasie, która jest zmienną viewmodel i upewnić się, że właściwość PropertyChanged INotifyPropertyChanged rozprzestrzenia się z klasy do rodzica.INotifyPropertyChanged w podklasie

Pozwól mi zilustrować na przykładzie:

(Window DataContext jest ustawiony do instancji 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"); 
     } 
    } 
    ... 
} 

Problemem w tym przypadku jest to, że podczas zmiany atrybutów a bound Textbox nie aktualizuje wiązania, ponieważ zakładam, że słucha zdarzenia PropertyChanged ViewModel, a nie instancji klasy OtherClass.

Jakieś pomysły, jak zaradzić tej sytuacji? Zastanawiałem się nad powiązaniem INotifyPropertyChanged Innego rodzaju z rodzica, ale musi istnieć lepszy sposób.

Odpowiedz

6

Dlaczego nie powiązać bezpośrednio z właściwością klasy zamiast z serwerem proxy?

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

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

Następnie w wiązaniu można po prostu odwołać się do własności poprzez podklasy

{Binding MyOtherClass.Attribute} 

Kropla martwy prosty przykład, ale to działa!

związany kod:

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 
} 

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

Upadłe proste przykłady to najlepsze przykłady :) – Moulde

+0

Jest to niepraktyczne, jeśli SomeSubClass zawiera stos właściwości. Czy naprawdę chcesz powielić wszystkie te właściwości? – Sean

+0

@Sean - Nie jestem pewien, co masz na myśli przez "duplikowanie wszystkich tych właściwości". W tym przykładzie to tylko zbieg okoliczności, że Imię jest zdefiniowane dla rodzica i dziecka. Nie ma to znaczenia dla podstawowego pytania. Przede wszystkim można powiązać bezpośrednio z właściwościami klasy potomnej, zamiast próbować użyć zmiennych proxy. W tym sensie wystąpiłoby zero powielania. – Josh

0

myślę klasa dominująca powinna zapisać się do dziecka propertyCahnged event..something jak:

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

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

NotifyChildAttributeChanged jest w zasadzie to metoda, która słucha tylko „atrybut” własności i wystrzeliwuje powiadomienia o PropertyChanged własny ..

Oczywiście nasza klasa nadrzędna musi implementować INotifyPropertyChanged, a także wszystkie ViewModels (najlepiej) i Twój DataContext wykryje zmianę.

4

Trzeba będzie zrobić coś takiego:

public class ViewModel { 
    public ViewModel() { 
     classInstance = new OtherClass(); 
     classInstance.PropertyChanged += HandleAttributeChanged; 
    } 

    private void HandleAttributeChanged(object Sender, NotifyPropertyChangedEventArgs args) { 
     PropertyChanged("Attribute"); 
    } 
} 

nie pokazać go tutaj, ale należy również wdrożyć IDisposable i zrezygnować z imprezy PropertyChanged na dziecko, w przeciwnym razie wycieku pamięci.

Alternatywnie można wystawić classInstance jako właściwość publiczną i ustawić powiązanie na: ViewModel.classInstance. Uwaga: musi to być właściwość, a nie samo pole.

+0

to działa na mnie zmianę NotifyPropertyChangedEventArgs dla PropertyChangedEventArgs. –