2009-05-05 99 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不能訪問它。

所以,我怎麼能實例化視圖的DataContext的是導致要選擇的DataTemplate中原來的視圖模型?

一個顯而易見的解決辦法是mmerge在ChildViewModel到ParentViewModel的屬性,但我寧願分開,因爲重複使用。

我相信答案是微不足道的,我只是想知道它是什麼。 :)

在此先感謝。

+0

順便說一句,我認爲你要想在代碼,以簡化的例子......對於「ChildView」之類的名字改變了你的類的名稱背後,是「QueueView」代替。 – 2009-05-05 16:45:45

+0

這是一個錯誤? – 2009-05-05 16:45:57

+0

是的,這是一個錯字。對不起:) – Jose 2009-05-07 12:45:41

回答

8

您應該簡單地刪除行:

DataContext = new ChildViewModel(); 

視圖的DataContext將被WPF自動設置。 DataTemplates總是有自己的數據上下文設置爲模板的數據(在這種情況下,視圖模型):

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

最終的結果是,你可以建立你的視圖模型分開(包括父母和子女類),然後對象只需將它們插入內容控件即可顯示它們。

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部分

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