2016-06-27 24 views
0

ich eine verschachtelte Ansicht Modellstruktur haben wie im folgenden Beispiel:Trigger-INotifyPropertyChanged.PropertyChanged für Immobilien auf abhängige/verschachtelte Ansicht Modell

public class SubViewModel : INotifyPropertyChanged 
{ 
    public string Property 
    { 
     get 
     { 
      // calculate result and return it 
     } 
    } 
} 

public class ViewModel : INotifyPropertyChanged 
{ 
    public SubViewModel Sub { get; set; } 

    public void MyMethod() 
    { 
     // executes code that changes some parameters such that Sub.Property changes 

     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Sub.Property")); 
    } 
} 

Es gibt Situationen, wenn eine Änderung in dem Modell übergeordneten Ansicht geschieht, dass der Einfluss Eigenschaften im verschachtelten Ansichtsmodell. Mit anderen Worten, eine Eigenschaft (SubViewModel.Property im Beispiel) im untergeordneten Ansichtsmodell ändert sich, aber das untergeordnete Ansichtsmodell weiß das nicht.

Ich möchte PropertyChanged in einer Weise aufrufen, die der WPF-Bindungs-Engine mitteilt, dass sich die Eigenschaft Property auf dem untergeordneten Ansichtsmodell Sub geändert hat. Ich habe versucht, alle möglichen Optionen, aber keiner hat bisher gearbeitet:

OnPropertyChanged(""); 
OnPropertyChanged("*"); 
OnPropertyChanged("Sub"); 
OnPropertyChanged("Sub.Property"); 
OnPropertyChanged("Sub.*"); 

Gibt es eine Möglichkeit, dies zu erreichen?

Hinweis: Ich weiß, dass das übergeordnete Ansichtsmodell eine Methode für das untergeordnete Ansichtsmodell aufrufen kann, die ein PropertyChanged-Ereignis im untergeordneten Ansichtsmodell auslöst. Ich habe meine Gründe, es nicht so zu machen.

+2

Vielleicht sollten Sie Ihre Gründe dafür auf diese Weise erklären. Dann können wir Ihnen vielleicht helfen, einen besseren Weg zu finden, Ihre Ziele zu erreichen. –

+1

Ernsthaft verstehe ich immer noch nicht ganz, was du meintest, aber du kannst 'OnPropertyChanged'' internal' machen und dann 'Sub.OnPropertyChanged (" Property ")' aufrufen. Ich weiß nicht, was du willst, aber wer weiß - das ist vielleicht das, was du brauchst. – Jai

+0

Warum können Sie das PropertyChanged-Ereignis nicht einfach von jeder Eigenschaft im Unteransichtsmodell aus auslösen? Wenn Sie den Subviewmodelinstance.PropertyName im Hauptansichtsmodell ändern, wird das entsprechende Ereignis automatisch ausgelöst. Es ist der normale Weg. Ich denke nicht, dass Sie das Ereignis auslösen müssen, indem Sie eine Funktion im Unteransichtsmodell aufrufen. – ViVi

Antwort

0
  • Aufruf OnPropertyChanged, wenn Sie das SubViewModel ändern.
  • Ihre SubviewModel sollten Sie in Ihrem MainViewModel
  • Ihrer Ansicht erstellt rufen müssen: "Datacontext = {Binding Sub}"
  • In Ihrem SubView es MUSTNOT ein Wort von "Datacontext" Be
  • In Ihrem SubView Sie die Eigenschaften wie folgt binden: "Beispiel = {MyProperty Binding}"

    public class SubViewModel : INotifyPropertyChanged 
    { 
        private string _MyProperty; 
        public string MyProperty 
        { 
         get { return _MyProperty; } 
         set { _MyProperty = value; 
          NotifyPropertyChanged(); 
         } 
        } 
    
        #region NotifyPropertyChanged 
        public event PropertyChangedEventHandler PropertyChanged; 
        private void NotifyPropertyChanged([CallerMemberName] string info = null) 
        { 
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info)); 
        } 
        #endregion 
    } 
    
    public class ViewModel : INotifyPropertyChanged 
    { 
        private SubViewModel _Sub; 
        public SubViewModel Sub 
        { 
         get { return _Sub; } 
         set { _Sub = value; 
         NotifyPropertyChanged(); 
         } 
        } 
    
        public void MyMethod() 
        { 
        // executes code that changes some parameters such that Sub.Property changes 
    
         NotifyPropertyChanged(); 
        } 
    
        #region NotifyPropertyChanged 
        public event PropertyChangedEventHandler PropertyChanged; 
        private void NotifyPropertyChanged([CallerMemberName] string info = null) 
        { 
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info)); 
        } 
    
        #endregion 
    } 
    
0

Sie sind eine zyklische Abhängigkeit zu schaffen zwischen ViewModel und SubViewModel. Dies führt zu einer starken Kopplung zwischen beiden, die niemals gut ist. Ich schlage eine andere Lösung vor. INotifyPropertyChanged bietet bereits die Infrastruktur, um genau das zu tun, was Sie wollen.

So hat SubViewModel eine Abhängigkeit von ViewModel. Ich nehme an, dass es den Wert einer der ViewModel Eigenschaften benötigt, um den Wert SubViewModel.Property zu berechnen. So ist die Lösung ganz natürlich hook up SubViewModel-ViewModel.PropertyChanged:

public class SubViewModel : INotifyPropertyChanged 
{ 
    private ViewModel parent; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public SubViewModel(ViewModel parent) 
    { 
     this.parent = parent; 
     // Hook up to parent's property changes. 
     this.parent.PropertyChanged += (sender, e) => 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SubProperty")); 
    } 

    public string SubProperty 
    { 
     get { return parent.Property; } 
    } 
} 

Beachten Sie, wie die Abhängigkeit von explizit gemacht wird, ein ViewModel im construcor von SubViewModel erwartet. Auf diese Weise sieht der nächste Programmierer sofort, dass ein SubViewModel eine ViewModel benötigt, um korrekt zu funktionieren und nicht eine nicht funktionierende SubViewModel konstruieren kann.

Der im Konstruktor definierte Event-Handler ist natürlich ziemlich vereinfacht. Besser machen Sie es eine private Methode, die e.PropertyName überprüft, bevor es etwas tut. Wie auch immer, es ist ein grundlegender Zweck, alle Kunden, die SubViewModel Eigentumsänderungen abonniert haben, als soons zu benachrichtigen, da ViewModel.Property geändert wurde.

Sie haben besser keine Beziehung von ViewModel zu SubViewModel, um eine zyklische Abhängigkeit zu vermeiden.Befreien Sie sich von der Sub Eigenschaft und implementieren ViewModel wie so:

public class ViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string property; 
    public string Property 
    { 
     get { return this.property; } 
     set 
     { 
      this.property = value; 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Property")); 
     } 
    } 
} 

Beachten Sie, wie die Umsetzung der ViewModel sieht genauso aus wie jede andere INotifyPropertyChanged Implementierung. Der Elternteil muss nicht wissen, was seine Kinder mit seinen Werten tun. Nur der Client von ViewModel implementieren die Logik, um ViewModel 's Eigenschaft Änderungen, nicht der Eltern zu behandeln.

Hier ist ein funktionierendes Beispiel für die Prüfung: https://dotnetfiddle.net/vQJBak

0

Ereignisse erstellen in SubViewModel, und das Ereignis auslösen, wenn sich etwas ändert. Das übergeordnete Ansichtsmodell wird dieses Ereignis abonnieren.

Das ist was für Ereignisse sind.

+0

Sollte es nicht umgekehrt sein (d. H. "SubViewModel" abonniert "ViewModel.PropertyChanged")? –

+0

@Abbondanza Sie bekommen die Idee. – AnjumSKhan