2009-05-05 103 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>