Prism 4.复合命令

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
        }
    }
原文地址:https://www.cnblogs.com/swobble/p/12809961.html