使用ViewModel的Mvvm Light ViewModel

时间:2013-03-12 18:56:31

标签: wpf mvvm

你们中的任何一个Mvvm Light Devotees如何处理以下情况。我有几个“Master”ViewModel使用他们自己的“Child”ViewModel实例。即。

Child ViewModel - “OrderLineItemListViewModel”视图模型,用于订单中的订单项列表。

父ViewModel - “OrderDetailViewModel”订单的视图模型。 父VIewModel - “OrderChargeViewModel”用于收取订单的视图模型。

两个父ViewModel都需要有一个OrderLineItem列表,两者都可以同时打开。目前,我已经设置了父ViewModel包含子ViewModel类型的属性,然后可以引用它。

public class ChildViewModel
{
    public ChildViewModel()
    {
       Items = new ObservableCollection<ListItemViewModel>
                   {
                      new ListItemViewModel("One"),
                      new ListItemViewMOdel("Two")
                   }
    }

    public ObservableCollection<ListItemViewModel> Items {get; private set;}
}

public class ParentViewModel
{
    public ParentViewModel()
    {
        ChildViewModel = new ChildViewModel();
    }

    public ChildViewModel ChildViewModel {get; set;}
}

<Window>
    <DataGrid ItemsSource={Binding ChildViewModel.Items} />
</Window>

现在,我觉得应该有一种方法可以使用ViewModelLocator和Messaging,但是我还没有想出一个干净的方法。我知道如何使用ViewModelLocator创建ViewModel的非单例实例,所以没关系。但是,我无法弄清楚的是如何让父ViewModel响应子ViewModel消息,并知道消息是否来自“它的”子ViewModel,因此应该采取行动。

任何人对如何处理这个问题都有任何建议,或者我应该像以前一样继续这样做?我想到的最重要的部分就是现在,我有选择地使用ViewModelLocator并且不确定它是否最终是直观的。

1 个答案:

答案 0 :(得分:1)

我不确定这个总数是否能回答你的问题,但我所拥有的是像你这样的嵌套视图模型。我有一个父视图/ viewmodel有一个集合(在这种情况下是一个实体框架导航属性)我希望子视图/ viewmodel与ineract一起使用。这样就可以在没有消息的情况下进行“交互”。

因此,例如,如果您想将父集合绑定到子视图模型中的组合框,您可以这样做(请注意,父视图和子视图是usercontrols,在父视图中,内容控件是绑定到子视图/ viewmodel):

<UserControl x:Class="EmployeeListView"
            DataContext="{Binding EmployeeList_VM, Source={StaticResource Locator}}"/>
    <ContentControl Name="DetailControl" DataContext="{Binding Path=Selection, Mode=TwoWay}" >
        <ComboBox Name="cbStatus" 
            ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.EmployeeStatus}"
            SelectedItem="{Binding ElementName=DetailControl, Path=DataContext.employee_status}"
            SelectedValuePath="idStatus"
            SelectedValue="{Binding idStatus, Mode=TwoWay, ValidatesOnDataErrors=True}"
            DisplayMemberPath="chrCode"/>
    </ContentControl>
</UserControl>

我尽量让它尽可能简单。请注意itemsource绑定到祖先usercontrol datacontext,其中包含我绑定的集合(EmployeeStatus)。这样,您的子视图模型可以与您的父VM集合/对象进行交互,而无需使用消息传递。否则我已经使用消息传递来定位特定的视图模型,如果这是你正在寻找的,但我认为上面可能更简单。

修改 在回答您的评论时,我认为这里的挑战是您想要解耦您的父/子视图模型,但同时您希望能够分辨哪些是“配对”。所以恕我直言,这样做的方法是创建一些类型的标志/标识符,在父视图模型和子视图模型上具有匹配的属性。我将在父视图模型的conrtuctor中设置此属性,并为子视图模型提供第二个构造函数,该构造函数在其构造函数中接受此标识符并设置该属性。然后我将使用messenger来定位父模型的viewmodel类型,并将标识符作为消息的参数传递。然后我将在父视图模型中注册信使以“监听”目标为其“类型”的消息,并检查标识符标志/参数是否与父视图模型中的标记/参数匹配。

通过为子视图模型提供两个构造函数,这将允许您仍然在其他位置使用子视图模型,而不是直接依赖父视图模型的属性类型,这可以避免将它们耦合在一起。

我希望这是有道理的。你说你熟悉了messenger,所以我没有发布一个如何定位类型并在消息中添加参数的例子,但是如果你愿意,我可以。

希望这有帮助。