合并两个自定义视图

时间:2017-06-23 14:21:58

标签: c# wpf mvvm

我对WPF和MVVM都很陌生,而且我试图解决这个问题......

我想要实现的目标

  • 有一个视图来搜索客户( CustomerSearchView )。
  • 有其他几个视图可以分别利用 CustomerSearchView

现状

我在其后面实现了前面提到的 CustomerSearchView CustomerSearchViewModel 。 ViewModel具有当前所选项的属性。

我实现了另一个视图,使用户能够查看和编辑客户( CustomerEditView )。当然,这个视图有一个自己的ViewModel - CustomerEditViewModel

现在,我想让用户在搜索视图中选择一个客户,然后该客户应该在详细信息视图中可见(并准备编辑)。 注意:很可能,将来我会在应用程序中使用单独的 CustomerSearchView 的多个窗口或页面。因此,将一般事件发送给中央事件处理程序似乎对我来说是错误的方法。

在坚持MVVM的同时实现这一目标的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

我认为你必须有某种一般的CustomerViewModel

假设父视图模型有一个属性:

public CustomerViewModel SelectedCustomer { /* INPC clutter */ }

为每个视图提供该类型的依赖项属性,并绑定它们。

<local:CustomerSearchView
    SelectedCustomer="{Binding SelectedCustomer}"
    />

<local:CustomerEditView
    EditedCustomer="{Binding SelectedCustomer}"
    />

CustomerSearchView将通过绑定或其他内容更新其SelectedCustomer。如果你不清楚如何用你所拥有的东西做到这一点,我们可以进入。

CustomerEditView会有这样的属性:

#region EditCustomer Property
public CustomerViewModel EditCustomer
{
    get { return (CustomerViewModel)GetValue(EditCustomerProperty); }
    set { SetValue(EditCustomerProperty, value); }
}

public static readonly DependencyProperty EditCustomerProperty =
    DependencyProperty.Register(nameof(EditCustomer), typeof(CustomerViewModel), typeof(CustomerEditView),
        new FrameworkPropertyMetadata(null, EditCustomer_PropertyChanged));

protected static void EditCustomer_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as MainWindow).OnEditCustomerChanged(e.OldValue);
}

private void OnEditCustomerChanged(object oldValue)
{
    //  Or maybe your CustomerEditViewModel can acquire a new customer 
    //  to edit in some other way. 
    DataContext = new CustomerEditViewModel(EditCustomer);
}
#endregion EditCustomer Property

但这不是我们在应用程序中执行此操作的方式。对于我们来说,我们的父视图模型将具有CustomerSearchViewModel CustomerSearch {...}属性和CustomerEditViewModel CustomerEdit {...}属性,以及上面的SelectedCustomer属性。在CustomerEditViewModel更改时,父视图模型将负责告知SelectedCustomer要编辑的客户。

然后我们在资源字典中有一些隐含的数据窗口,它们被合并到主视图中:

<DataTemplate DataType="{vm:CustomerSearchViewModel}">
    <vw:CustomerSearchView />
</DataTemplate>

<DataTemplate DataType="{vm:CustomerEditViewModel}">
    <vw:CustomerEditView />
</DataTemplate>

然后在包含搜索和编辑视图的父视图中:

<ContentControl Content="{Binding CustomerSearch}" />
<ContentControl Content="{Binding CustomerEdit}" />

使用这种“viewmodel-first”方法,视图永远不会提供自己的视图模型。另一方面,这会使父视图模型稍微涉及UI设计问题,例如客户编辑器所在的位置。

答案 1 :(得分:-1)

有多种方法可以做到,但我使用的方法是让一个父ViewModel能够保存对两个ViewModel的引用。

然后,这位家长有责任通知每个孩子另一个孩子的变化。

另一种方法是使用服务类,该服务类将保存数据并为修改此数据提供一些事件(这些事件将在您的服务属性&#39; setters中调用)。 您的两个ViewModel将订阅他们感兴趣的事件(因此属性),并做出相应的反应。

对于您的应用程序的未来,如果您不希望中央ViewModel处理所有事情,我会采用服务方式。

编辑:如果downvote是因为我没有显示代码,我也没有显示任何一个,所以我不能做更多的事情。