Что если бы у вас был агрегатный объект 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, которое можно смоделировать для ваших тестов.