如果您有一个指定适当行为的聚合 Command 对象怎么办?我将尝试将您的问题具体化一点,如果我错了,请纠正我:
假设您的应用有两个相关部分 - 一个可以缩放和平移等的地图组件,以及一组控件,它们提供用于缩放、平移和在它们之间选择的用户界面 - 有点像一组模式选择器。您不希望它们中的任何一个直接引用另一个,并且诱惑是让地图直接了解其控件集,以便它可以从它们捕获事件并适当地切换模式状态。
解决这个问题的一种方法是在一个对象中注入一组 CompositeCommands(可从Prism Application Guidance 获得)库。通过这种方式,您可以获得解耦和对接口的强烈描述(如果您愿意,也可以使用事件)。
public class MapNavigationCommands{
public static CompositeCommand startPanning = new CompositeCommand();
public static CompositeCommand startZooming = new CompositeCommand();
public static CompositeCommand setViewbox = new CompositeCommand();
}
您的模式控件,在功能区中,向您的 DI 框架注册以进行注入(不想在此示例中引入 DI,我只是直接引用了这些静态成员)。
public class ModeControls : UserControl{
...
public void PanButtonSelected(object sender, RoutedEventArgs e){
MapNavigationCommands.StartPanning.Execute(this); //It doesn't really care who sent it, it's just good event practice to specify the event/command source.
}
}
或者,在 XAML 中:
...
<Button Command={x:Static yourXmlns:MapNavigationCommands.StartPanning}>Start</Button>
...
现在,在地图一侧:
public class PannableMapViewModel{
public PannableMapViewModel(){
MapNavigationCommands.StartPanning.RegisterCommand(new DelegateCommand<object>(StartPanning));
MapNavigationCommands.SetViewbox.RegisterCommand(new DelegateCommand<Rectangle>(SetViewBox));
}
private void StartPanning(object sender){
this.SetMode(Mode.Pan); //Or as appropriate to your application. The View is bound to this mode state
}
private void SetViewbox(Rectangle newView){
//Apply appropriate transforms. The View is bound to your transform state.
}
}
现在您在两个控件之间有了一个解耦的、强指定的接口,保持 ViewModel 分离,可以为您的测试模拟出来。