本文参考Prism官方示例
命令使用
Prism提供了两种命令:DelegateCommand和CompositeCommand。
DelegateCommand
DelegateCommand封装了两个委托:Execute和CanExecute,使用如下:
// view
// viewmodel
public DelegateCommand ExecuteDelegateCommand { get; private set; }
public MainWindowViewModel()
{
ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);
}
private void Execute()
{
UpdateText = $"Updated: {DateTime.Now}";
}
private bool CanExecute()
{
return IsEnabled;
}
CompositeCommand
CompositeCommand为复合命令,由多个子命令构成。当调用CompositeCommand时,将依次调用每个子命令。默认情况下,当所有子命令CanExecute均返回true时才会执行CompositeCommand。使用方法如下:
// Project.Core中定义接口及实现
public interface IApplicationCommands
{
CompositeCommand SaveCommand { get; }
}
public class ApplicationCommands : IApplicationCommands
{
private CompositeCommand _saveCommand = new CompositeCommand();
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
}
// App.xaml.cs中注册单例对象
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<
IApplicationCommands, ApplicationCommands>();
}
// viewmodel中添加子命令
public TabViewModel(IApplicationCommands applicationCommands)
{
_applicationCommands = applicationCommands;
UpdateCommand = new DelegateCommand(Update).ObservesCanExecute(
() => CanUpdate);
_applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}
// view中执行命令(需在对应的viewmodel的构造函数中传入IApplicationCommands实例)
EventAggregator
EventAggregator是一种事件机制,解决了松耦合模块间的通信问题。使用方法如下:
// Project.core中声明事件类型
public class MessageSentEvent : PubSubEvent
{
}
// viewmodel中发布事件
IEventAggregator _ea;
public MessageViewModel(IEventAggregator ea)
{
_ea = ea;
// 发布事件的命令
SendMessageCommand = new DelegateCommand(SendMessage);
}
private void SendMessage()
{
_ea.GetEvent().Publish(Message);
}
// viewmodel中订阅事件
IEventAggregator _ea;
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
_ea.GetEvent().Subscribe(MessageReceived);
// 如下方式可以过滤事件,可通过第二个参数指定处理线程
// _ea.GetEvent().Subscribe(MessageReceived,
ThreadOption.PublisherThread, false,
(filter) => filter.Contains("Brian"));
}
private void MessageReceived(string message)
{
// hava a message
}
RegionNavigation
区别于View Discovery和View Injection,RegionNavigation可通过region名称与要导航的视图名称实现更通用的视图导航功能,使用如下:
// 模块类中注册导航视图
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation();
}
// xaml导航命令
// viewmodel实现导航
public DelegateCommand NavigateCommand { get; private set; }
public MainWindowViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
NavigateCommand = new DelegateCommand(Navigate);
}
private void Navigate(string navigatePath)
{
if (navigatePath != null)
_regionManager.RequestNavigate("ContentRegion",
navigatePath, NavigationCompleted);
}
// 可指定导航完成回调
private void NavigationCompleted(NavigationResult result)
{
// ...
}
INavigationAware接口
INavigationAware接口包含三个方法:OnNavigatedFrom、OnNavigatedTo、IsNavigationTarge。当ViewAViewModel及ViewBViewModel均实现了INavigationAware接口,ViewA导航到ViewB时,先调用ViewA的OnNavigatedFrom方法,然后调用ViewB的IsNavigationTarge,当其返回true时,调用OnNavigatedTo方法,若IsNavigationTarge返回false,创建新ViewB。示例如下:
public class ViewAViewModel : BindableBase, INavigationAware
{
public void OnNavigatedTo(NavigationContext navigationContext)
{
// ...
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// ...
}
}
IConfirmNavigationRequest接口
IConfirmNavigationRequest接口继承了INavigationAware接口,并添加了ConfirmNavigationRequest方法。若ViewAViewModel实现了IConfirmNavigationRequest接口,当ViewA导航到ViewB时,先调用ConfirmNavigationRequest方法,若continuationCallback()参数为true,将继续执行导航,执行OnNavigatedFrom方法;若continuationCallback()参数为false,停止导航。示例如下:
public class ViewAViewModel : BindableBase, IConfirmNavigationRequest
{
public void ConfirmNavigationRequest(NavigationContext navigationContext,
Action continuationCallback)
{
bool result = true;
if (MessageBox.Show("Do you to navigate?", "Navigate?",
MessageBoxButton.YesNo) == MessageBoxResult.No)
result = false;
continuationCallback(result);
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
}
IRegionMemberLifetime接口
IRegionMemberLifetime接口只包含一个KeepAlive只读属性。其默认值为true,若其为false,则当该region导航到其它视图时,实现了该接口的当前视图将从IRegion.Views集合中移除并回收。若为true,即使导航到其它视图,该视图依然存在于IRegion.Views集合。示例如下:
public class ViewAViewModel : BindableBase, IRegionMemberLifetime
{
public bool KeepAlive
{
get
{
return false;
}
}
}
参数传递
可使用NavigationParameters实现导航时的参数传递,使用方法如下:
// 导航命令
private void PersonSelected(Person person)
{
var parameters = new NavigationParameters();
parameters.Add("person", person);
if (person != null)
_regionManager.RequestNavigate("PersonDetailsRegion",
"PersonDetail", parameters);
}
// 参数处理
public void OnNavigatedTo(NavigationContext navigationContext)
{
var person = navigationContext.Parameters["person"] as Person;
// ...
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
var person = navigationContext.Parameters["person"] as Person;
// ...
}
Navigation Journal
Navigation Journal可以记录导航的过程,其通过IRegionNavigationJournal接口实现。通过Navigation Journal,可以实现向前/向后导航。示例如下:
// GoForward
public class PersonListViewModel : BindableBase, INavigationAware
{
IRegionNavigationJournal _journal;
public DelegateCommand GoForwardCommand { get; set; }
public PersonListViewModel(IRegionManager regionManager)
{
...
GoForwardCommand = new DelegateCommand(GoForward, CanGoForward);
}
// IRegionNavigationJournal.GoBack到行至此
public void OnNavigatedTo(NavigationContext navigationContext)
{
_journal = navigationContext.NavigationService.Journal;
GoForwardCommand.RaiseCanExecuteChanged();
}
private void GoForward()
{
_journal.GoForward();
}
private bool CanGoForward()
{
return _journal != null && _journal.CanGoForward;
}
}
// GoBack
public class PersonDetailViewModel : BindableBase, INavigationAware
{
IRegionNavigationJournal _journal;
public DelegateCommand GoBackCommand { get; set; }
public PersonDetailViewModel()
{
GoBackCommand = new DelegateCommand(GoBack);
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_journal = navigationContext.NavigationService.Journal;
}
private void GoBack()
{
_journal.GoBack();
}
}
InvokeCommandAction
Prism提供了InvokeCommandAction以使ViewModel处理View的事件,示例如下:
// view xaml
// viewmodel
public DelegateCommand