2009-05-05 11 views
8

Potrzebuję dowiedzieć się, jak komunikować się między ViewModels. Jestem nowy w MVVM, więc proszę bądź uprzejmy.Wzór MVVM, pytanie DataModel DataContext

Oto dumbed dół Przykład

definicje klasy (zakładając, że mam podpięty zdarzenie Child.PropertyChanged w ParentViewModel):

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"); 
     } 
    } 
} 

Oto, co można zobaczyć w słowniku zasobów

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

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

i kod identyfikatora ChildView:

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

Oczywistym problemem jest to, że po utworzeniu instancji ChildView (poprzez wybór z DataTemplate) tworzy ona nową klasę ChildViewModel i ParentViewModel nie ma do niej dostępu.

Jak utworzyć instancję DataContext widoku jako oryginalny ViewModel, który spowodował wybór DataTemplate?

Oczywistym rozwiązaniem jest zminiaturyzowanie właściwości w ChildViewModel do ParentViewModel, ale wolałbym go oddzielić, ponieważ do ponownego użycia.

Jestem pewien, że odpowiedź jest banalna, po prostu chciałbym wiedzieć, co to jest. :)

Z góry dziękuję.

+0

Przy okazji, zakładam, że zmieniliście nazwy swoich klas w celu uproszczenia przykładu ... Zamiast tego nazwa klasy dla "ChildView" w kodzie jest "QueueView". –

+0

Czy to była literówka? –

+0

Tak, to był błąd. przepraszam :) – Jose

Odpowiedz

8

należy po prostu usunąć wiersz:

DataContext = new ChildViewModel(); 

DataContext z widoku zostanie ustawiony automatycznie przez WPF. DataTemplates zawsze ich kontekst danych ustawione do danych dla szablonu (w tym przypadku ViewModel):

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

Końcowym rezultatem jest to, że można zbudować widok modelu obiektów osobno (obie klasy rodzic i dziecko), a następnie wyświetlaj je później, po prostu podłączając je do kontroli treści.

+0

Jeśli intencją jest, aby ParentView zawierał ChildView, w jaki sposób to samodzielnie ustawić DataContext ChildView na ParentViewModel.Child? –

+0

Scenariusz prawdopodobnie wyglądałby mniej więcej tak: W metodzie fabryki lub konstruktora utworzono obiekt nadrzędny i potomny. Ten obiekt zostanie przekazany do widoku. –

+0

Widok może wyświetlać element nadrzędny w jednym formancie treści, a element potomny w innym lub wyświetlać zarówno element nadrzędny, jak i element podrzędny w formancie nagłówka. –

1

Załóżmy, że masz QueueView, który używa QueueViewModel.

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"); 
     } 
    } 
} 

- QueueView część

<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

Twoje próbki kodu naprawdę nie wydają się być związane z pytaniem. Czy jedno lub obie z nas tęskniły za tym punktem? –

+0

Zakładałem, że Model Dziecko był własnością Modelu Rodziców. (np. zamówienie + lista szczegółów zamówienia). W takim przypadku możesz używać powiadomień o zmianie właściwości do komunikacji w modelu widoku. Ale jeśli są to osobne modele widoku, możesz użyć wzoru mediatora do komunikacji. –