1

我有一个应用程序,我有一个程序集。

在应用程序中,我有一个窗口,在程序集中我有一个用户控件。

窗口中有一个用户控件的实例。

用户控件和窗口都由单独的视图模型支持。

在用户控件中,有一个按钮。该按钮应根据用户控件的视图模型的状态启用/禁用。单击按钮时,需要根据用户控件的视图模型中的信息进行处理,但需要由窗口的视图模型完成。(需要做的事情的某些方面是并且应该在用户控制范围之外。)

这里有一个转折点——这个用户控件不会专门用于这个窗口,它可能会用在另一个窗口中,或者用在第三个窗口中使用的控件中。不允许用户控件知道包含它的窗口或控件的类型,或者在单击其按钮时正在处理该进程。

那么该怎么办?

在程序集中定义一个命令,并将用户控件的按钮绑定到它,将用户控件的视图模型作为命令参数传递?那么,如何将命令绑定到窗口的视图模型?

或者我应该在用户控件的视图模型中定义命令,然后引发一个事件来告诉父窗口需要采取适当的行动?

我不清楚哪个更干净。

4

4 回答 4

3

如果您总是知道父母的财产将以相同的名称公开,那么您可以做这样的事情,这对我有用很多次:

Command={Binding Parent.DataContext.SomeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}

这将获取用户控件,然后转到父级并获取该数据上下文并将其绑定到该命令。当用户控件将被许多公开相同命令的窗口/控件包围时,此方法有效(您可以在此处实现接口)。

然后,您可以将用户控件的视图模型传递给命令(同样,实现一些接口),如下所示:

CommandParaemter={Binding }
于 2012-07-31T20:35:34.390 回答
0

您可以使用 Messenger 结构在 ViewModel 之间进行通信。

MVVMLight 包含一个你可以使用或者你可以自己编写的。

在这样做之前,请确保您确实正确地分离了职责,否则您最终会得到意大利面条消息代码。

于 2012-07-31T20:34:57.573 回答
0

你的视图模型应该有层次结构,就像你的控件一样。主窗口有一个子用户控件。主视图模型应该能够与用户控制视图模型连接(并在需要时分配它)。这是我的做法:

public class MainVM:NotificationObject
{
  // Make this a Notify Property
  public UserVM userVM { get{return _userVM;}; set {_userVM = value; RaisePropertyChanged("userVM");}

  public MainVM
{
  userVM = new UserVM();
  userVM.ExecuteCmd = new DelegateCommand (yourAction);

}

}

public class UserVM:NotificationObject
{

public DelegateCommand ExecuteCmd {get{return _executeCmd;} set{_executeCmd = value; RaisePropertyChanged("ExecuteCmd");
}

}

XAML:

<local:urUserCtrl DataContext={Binding userVM}/>

这当然是伪代码

于 2012-07-31T20:59:06.097 回答
0

听起来像是策略模式的一个案例。http://en.wikipedia.org/wiki/Strategy_pattern

为可以分配给 UserControl 的视图模型(或用于初始化它)的策略对象定义一个接口。该接口定义了使策略对象能够从 UserControl 视图模型中检索处理所需的数据所需的任何属性/方法/事件,以及将处理结果返回给 UserControl 视图模型的方法。

然后创建该策略对象的具体实现,该对象与 Window 的视图模型协作以执行所需的任何任务。在这种情况下,Window 的视图模型甚至可能实现策略接口本身。

然后可以使用策略对象的其他具体实现来初始化其他场景中的其他 UserControl 实例,这些实现执行相同的所需任务,但可能以非常不同的方式。

于 2012-07-31T21:12:56.647 回答