03_Prism_命令


Prism 提供了 DelegateCommand 类来实现命令。界面中的UI控件与命令之间的交互可以是双向的,可以启用或禁用底层命令时自动启用或禁用UI。

DelegateCommand

// DelegateCommand.cs
public class DelegateCommand : DelegateCommandBase
{
    public DelegateCommand(Action executeMethod,Func canExecuteMethod ): base((o) => executeMethod((T)o), (o) => canExecuteMethod((T)o))
    {
        ...
    }
}

View调用 DelegateCommand

控件状态变更通知

ViewModel 通常需要指示命令 CanExecute 状态的变更,一边UI控件更新是否可用状态。

RaisCanExecuteChanged

当需要手动更新绑定的 UI 元素的状态时,调用 RaisCanExecuteChanged 方法。

private bool _isEnabled;
public bool IsEnabled
{
    get { return _isEnabled; }
    set
    {
        SetProperty(ref _isEnabled, value);
        SubmitCommand.RaiseCanExecuteChanged();
    }
}

ObservesProperty

观察属性值的变化,当属性值改变时自动调用 RaisCanExecuteChanged 方法来通知 UI 状态变化。

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }

    bool CanSubmit()
    {
        return IsEnabled;
    }
}

使用 ObservesProperty 方法时,可以同时观察多个属性。ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave)

ObservesCanExecute

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit).ObservesCanExecute(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }
}

异步任务

有时候会需要异步执行 Execute 方法,此时会想到一个 AsyncCommand ,但ICommand 本质上是同步的,所以 AsyncCommand 这种是错误的。

Execute 和 CanExecute 委托事件可以使用 async void 进行修饰。

// 方法一
public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit);
    }

    async void Submit()
    {
        await SomeAsyncMethod();
    }
}

// 方法二
public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(async ()=> await Submit());
    }

    Task Submit()
    {
        return SomeAsyncMethod();
    }
}

复合命令

有时候,希望程序能够一次性调用多个命令。复合命令 CompositeCommand 表示由多个子命令组成的命令。

// 创建一个复合命令
public class ApplicationCommands
{
    private CompositeCommand _saveCommand = new CompositeCommand();
    public CompositeCommand SaveCommand
    {
        get { return _saveCommand; }
    }
}

通常,CompositeCommands 在整个应用程序中共享,并且需要全局可用。可以通过依赖注入或静态类来定义 CompositeCommands为单例。建议使用依赖注入的方法。

依赖注入

// 创建一个接口
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();
    }
}

现在可以在ViewModel中注册子命令到复合命令了。

// 复合命令,用于绑定到UI
private IApplicationCommands _applicationCommands;
public IApplicationCommands ApplicationCommands
{
    get { return _applicationCommands; }
    set { SetProperty(ref _applicationCommands, value); }
}

// 子命令
public DelegateCommand UpdateCommand { get; private set; }

public TabViewModel(IApplicationCommands applicationCommands)
{
    ApplicationCommands = applicationCommands;
    UpdateCommand = new DelegateCommand(Update);
    applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}

绑定到UI元素

使用静态类

public static class ApplicationCommands
{
    public static CompositeCommand SaveCommand = new CompositeCommand();
}

在 ViewModel 中,将子命令关联到静态 ApplicationCommands 类。

public DelegateCommand UpdateCommand { get; private set; }

public TabViewModel()
{
    UpdateCommand = new DelegateCommand(Update);
    ApplicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}

绑定到UI元素

我的公众号 HelloPragram