2009-05-05 16 views
8

Ich muss herausfinden, wie man zwischen ViewModels kommuniziert. Ich bin neu in MVVM, also bitte sei nett.MVVM-Muster, ViewModel DataContext-Frage

Hier ist ein verdummtes Beispiel

Klassendefinitionen (davon ausgehen, dass ich das Child.PropertyChanged Ereignis in der ParentViewModel angeschlossen habe):

public class ParentViewModel : ViewModelBase 
{ 
    public ChildViewModel Child { get; set; } 
} 

public class ChildViewModel : ViewModelBase 
{ 
    String _FirstName; 
    public String FirstName 
    { 
     get { return _FirstName; } 
     set 
     { 
      _FirstName = value; 
      OnPropertyChanged("FirstName"); 
     } 
    } 
} 

Hier ist, was Sie im Ressourcenverzeichnis sehen

<DataTemplate DataType="{x:Type vm:ParentViewModel}"> 
    <vw:ParentView/> 
</DataTemplate> 

<DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
    <vw:ChildView/> 
</DataTemplate> 

und der Code-Behind der ChildView:

public partial class ChildView : UserControl 
{ 
    public QueueView() 
    { 
     InitializeComponent(); 
     DataContext = new ChildViewModel(); 
    } 
} 

Das offensichtliche Problem ist, dass, wenn die ChildView instanziiert wird (über die Auswahl aus der DataTemplate) erstellt es eine neue ChildViewModel-Klasse und das ParentViewModel hat keinen Zugriff darauf.

Wie kann ich den DataContext der View als das ursprüngliche ViewModel instanziieren, das zur Auswahl der DataTemplate führte?

Eine offensichtliche Lösung besteht darin, die Eigenschaften im ChildViewModel in das ParentViewModel einzufügen, aber ich würde es lieber zur Wiederverwendung trennen.

Ich bin sicher, die Antwort ist trivial, ich möchte nur wissen, was es ist. :)

Vielen Dank im Voraus.

+0

Ich nehme übrigens an, dass Sie die Namen Ihrer Klassen geändert haben, um das Beispiel zu vereinfachen ... Der Klassenname für die "ChildView" in Code hinter ist stattdessen "QueueView". –

+0

War das ein Tippfehler? –

+0

Ja das war ein Tippfehler. Entschuldigung :) – Jose

Antwort

8

Sie sollten einfach entfernen Sie die Zeile:

DataContext = new ChildViewModel(); 

Die DataContext der Ansicht wird automatisch von WPF eingestellt werden. DataTemplates immer auf die Daten, um ihren Datenkontext (das Ansichtsmodell in diesem Fall) für die Vorlage festgelegt hat:

<DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
    <vw:ChildView/> 
</DataTemplate> 

Das Endergebnis ist, dass Sie die Ansicht Modell (beiden Eltern und Kind Klassen) Objekte separat bauen und dann Zeigen Sie sie später an, indem Sie sie einfach in die Inhaltssteuerelemente einfügen.

+0

Wenn die Absicht ist, dass eine ParentView eine ChildView enthält, wie legt dies den DataContext von ChildView als ParentViewModel.Child fest? –

+0

Nun, das Szenario würde wahrscheinlich in etwa so aussehen: In einer Factory- oder Builder-Methode würden Sie das Eltern- und Kindobjekt erstellen. Dieses Objekt würde einer Ansicht übergeben werden. –

+0

Die Ansicht würde entweder das übergeordnete Element in einem Inhaltssteuerelement und das untergeordnete Element in einem anderen anzeigen, oder es würde sowohl das übergeordnete Element als auch das untergeordnete Element in einem HeaderedContent-Steuerelement anzeigen. –

1

Nehmen wir an, Sie haben eine QueueView, die ein QueueViewModel verwendet.

public class QueueViewModel : INotifyPropertyChanged 
{ 
    public ParentType Parent { get; set; } 

    public QueueViewModel(ParentType parent) 
    { 
     this.Parent = parent; 
     foreach (ChildType child in Parent) 
     { 
      child.PropertyChanged += delegate(object sender, 
       PropertyChangedEventArgs e) 
      { 
       if (e.PropertyName != "IsSelected") 
        return; 

       //do something like this: 
       Parent.IsSelected = AllChildrenAreSelected(); 
      }; 
     } 
    } 

} 

public class ParentType : INotifyPropertyChanged 
{ 
    private bool _isSelected; 

    public IList<ChildType> Children { get; set; } 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      OnPropertyChanged("IsSelected"); 
     } 
    } 
} 

public class ChildType : INotifyPropertyChanged 
{ 
    private string _name; 
    private bool _isSelected; 

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

    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      OnPropertyChanged("IsSelected"); 
     } 
    } 
} 

- Queue-Ansicht Teil

<StackPanel> 
<CheckBlock Text="{Binding Path=Parent.Name}" 
      IsChecked="{Binding Parent.IsSelected}"/> 
<ItemsControl ItemsSource="{Binding Path=Parent.Children}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate>          
      <CheckBox Content="{Binding Path=Name}" 
         IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"/> 
     </DataTemplate> 
    <ItemsControl.ItemTemplate> 
</ItemsControl> 
</StackPanel> 
+0

Ihre Code-Beispiele scheinen nicht wirklich auf die Frage bezogen zu sein. Haben einer oder beide von uns den Punkt verpasst? –

+0

Ich nahm an, dass das Kindmodell eine Eigenschaft des Elternmodells war. (z. B. Bestellung + Liste der Bestelldetails). In diesem Fall können Sie mithilfe von Property-Change-Benachrichtigungen im View-Modell kommunizieren. Wenn es sich jedoch um separate Ansichtsmodelle handelt, können Sie das Mediator-Muster zur Kommunikation verwenden. –