Prism 4.复合命令
常规:一个ViewModel提供一个Command,绑定到一个View中去
但是,有时会有这样的情况:在一个父控件中,需要触发他的多个子控件的命令。
(感觉,类似,路由事件。。。)
CompositeCommand
这里面维护了一组子命令,当这个复合命令触发时,里面的一组子命令都会执行
如果所有子命令都可以执行的话才会触发(CanExcute==true),如果可以触发每个命令会触发自己的Excute方法
创建CompositeCommand命令
private CompositeCommand _saveCommand = new CompositeCommand();
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
CompositeCommand需要全局使用,一般通过DI定义为单例,或者用static实现
1.DI生成,定义为单例
public interface IApplicationCommands
{
CompositeCommand SaveCommand { get; }
}
public class ApplicationCommands : IApplicationCommands
{
private CompositeCommand _saveCommand = new CompositeCommand();
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
}
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IApplicationCommands, ApplicationCommands>();
}
}
已经注册为单例模式,下一步将子command注册到复合命令
public DelegateCommand UpdateCommand { get; private set; }
public TabViewModel(IApplicationCommands applicationCommands)
{
UpdateCommand = new DelegateCommand(Update);
applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}
2.static生成
public static class ApplicationCommands
{
public static CompositeCommand SaveCommand = new CompositeCommand();
}
public DelegateCommand UpdateCommand { get; private set; }
public TabViewModel()
{
UpdateCommand = new DelegateCommand(Update);
ApplicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}
提示:为了保持代码的可维护性和测试性,建议用DI生成的方式哦
绑定CompositeCommand到UI
用DI的方式:
ViewModel,首先你得暴露出一个CompositeCommand的属性,然后在构造函数中传入CompositeCommand实例
public class MainWindowViewModel : BindableBase
{
private IApplicationCommands _applicationCommands;
public IApplicationCommands ApplicationCommands
{
get { return _applicationCommands; }
set { SetProperty(ref _applicationCommands, value); }
}
public MainWindowViewModel(IApplicationCommands applicationCommands)
{
ApplicationCommands = applicationCommands;
}
}
View
<Button Content="Save" Command="{Binding ApplicationCommands.SaveCommand}"/>
用Static的方式
View直接绑定
<Button Content="Save" Command="{x:Static local:ApplicationCommands.SaveCommand}" />
如何减少子类命令比如
如果遇到了比如你想回收View/Viewmodel的情况,你得取消注册命令
public void Destroy()
{
_applicationCommands.UnregisterCommand(UpdateCommand);
}
警告:当你不需要View/Viewmodel的时候,你必须解除注册CompositeCommand,否则会导致内存泄漏
只在活动窗口去执行命令
情形:父控件点击,只有激活窗口才响应命令
private CompositeCommand _saveCommand = new CompositeCommand(true);
这个true的意思:
1 CanExecute,当所有激活的子控件的CanExecute==true,才为true,不考虑没有激活的控件
2 只执行激活的控件的命令.Excute
如何通知子控件的激活状态,实现IActiveAware接口
public class TabViewModel : BindableBase, IActiveAware
{
private bool _isActive;
public bool IsActive
{
get { return _isActive; }
set
{
_isActive = value;
OnIsActiveChanged();
}
}
public event EventHandler IsActiveChanged;
public DelegateCommand UpdateCommand { get; private set; }
public TabViewModel(IApplicationCommands applicationCommands)
{
UpdateCommand = new DelegateCommand(Update);
applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}
private void Update()
{
//implement logic
}
private void OnIsActiveChanged()
{
UpdateCommand.IsActive = IsActive; //set the command as active
IsActiveChanged?.Invoke(this, new EventArgs()); //invoke the event for all listeners
}
}