我有以下ViewModel,我在构造函数中实例化CompositeCommand:
public class ViewImportPreviewViewModel:BindableBase
{
private IEventAggregator eventAggregator; //event aggregator to enable Studio button in different ViewModel
private readonly IRegionManager regionManager; //region manager for navigation to the main menu
public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click
public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
{
this.eventAggregator = eventAggregator;
this.regionManager = regionManager;
this.finalizeImportClick = finalizeImportClick;
finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click
}
//subscriber method to the firs delegate command registered with finalize button click
private void NavigateToMain(string argument)
{
//it enables the studio button after import and sends it to the main menu view XAML
eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");
//it navigates to the main menu after import
regionManager.RequestNavigate("ScreenNavigationRegion", argument);
//publish an event for the main buttons viewmodel and then over there try to fade in main buttons
eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
}
}
现在我想进行控制反转,并在类外部实例化CompositeCommand,然后通过Unity Container注入它,如下所示:
CompositeCommand myCommand = new CompositeCommand();
container.RegisterInstance<CompositeCommand>(myCommand);
然后在模块初始化时,我这样做:
NavigateToMain(string argument)
虽然命令已注册,但我没有收到任何错误,但RegisterCommand
没有被调用。
我尝试注册类型,但CompositeCommand继承了ICommand接口,该接口不包含/[^\u0000-\u024F\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF]/g
方法的定义。
答案 0 :(得分:2)
实际上,CompositeCommands是单例/静态非常常见,因为多个松散耦合的模块将注册相同的CompositeCommand。这是标准的,也是预期的。
当然,您希望这样做以保持ViewModel的可测试性。您希望通过ctor知道您的依赖项。您不希望在VM中调用静态方法。
您要做的是创建一个自定义界面,如IApplicationCommands,并为您要公开的每个CompositeCommand提供属性,然后确保将该界面注册到您的容器。我还建议提供一个静态版本,以便您可以将按钮绑定到compositeCommands而无需引用绑定,这非常好。
所以也许是这样的:
//Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
CompositeCommand SaveAllCommand { get; }
}
public static class GlobalCommands
{
public static CompositeCommand SaveAllCommand = new CompositeCommand();
}
//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
public CompositeCommand SaveAllCommand
{
get { return GlobalCommands.SaveAllCommand; }
}
}
并注册如下:
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
// and remove the call to a static class in our VM. This keeps us testable.
Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();