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元素