2009-05-05 11 views
8

ViewModels間の通信方法を理解する必要があります。私はMVVMに新しいので、親切にしてください。ここでMVVMパターン、ViewModel DataContext質問

がダウン易しく書き直さ例は

クラス定義(私はParentViewModelにChild.PropertyChangedイベントを夢中にしていることを前提とし)です:

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

ここでは、リソースディクショナリ

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

<DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
    <vw:ChildView/> 
</DataTemplate> 
で見るものです

とChildViewのコードビハインド:

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

明白な問題は、ChildViewが(DataTemplateからの選択によって)インスタンス化されると、新しいChildViewModelクラスを作成し、ParentViewModelはそのインスタンスにアクセスできないということです。

DataTemplateが選択された元のViewModelになるように、ViewのDataContextをインスタンス化するにはどうすればよいですか?

明白な修正点は、ChildViewModelのプロパティをParentViewModelにmmergeすることですが、再利用のために分離することになります。

私はその答えが自明であると確信しています、私はちょうどそれが何であるか知りたいです。 :)

ありがとうございます。

DataContext = new ChildViewModel(); 

は、ビューのDataContextは、WPFによって自動的に設定されます。

+0

ところで、例を単純化するためにクラス名を変更したとします。コードビハインドの "ChildView"のクラス名は、代わりに "QueueView"です。 –

+0

これは誤植ですか? –

+0

はい、これはタイプミスでした。申し訳ありません:) – Jose

答えて

8

あなたは、単に行を削除する必要があります。 DataTemplatesは、常に自分のデータコンテキストが(この場合のViewModelに)テンプレートのデータに設定されています:

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

最終結果はあなたのビューモデルを個別に(両方の親と子のクラス)、その後、オブジェクトを構築することができるということですコンテンツコントロールにプラグインするだけで後で表示できます。

+0

ParentViewがChildViewを含むことを意図している場合、これだけでChildViewのDataContextをParentViewModel.Childに設定する方法はありますか? –

+0

シナリオはおそらく次のようになります。 ファクトリまたはビルダーメソッドでは、親オブジェクトと子オブジェクトを作成します。このオブジェクトはビューに渡されます。 –

+0

ビューでは、1つのコンテンツコントロールに親を表示し、別のコンテンツコントロールには子を表示するか、親と子の両方をHeaderedContentコントロールに表示します。 –

1

QueueViewModelを使用するQueueViewがあるとします。

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部

+0

あなたのコードサンプルは本当に質問に関連しているようには見えません。私たちのどちらかまたは両方がポイントを逃しましたか? –

+0

私は、子モデルが親モデルのプロパティであると仮定していました。 (例:Order + Order Detailsのリスト)。この場合、プロパティー - 変更通知を使用して、ビュー・モデル内で通信することができます。しかし、別々のビューモデルである場合は、メディエータパターンを使用して通信できます。 –

5
<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> 

MVVMのアプローチを使用してのviewmodels間で通信するための最も簡単な方法は、メディエータ・パターン(プリズムでEventAggregator)を使用することです。このアプローチの良い例は、以下のリンクで見ることができます。

  1. MVVM Mediator Pattern by Sacha Barber
  2. MVVM + Mediator by marlon grech

またMVVM sampleプロジェクトの枠組みをチェックしてください。

関連する問題