本文参考Prism官网示例

命令应用

Prism提供了两种命令:DelegateCommand和CompositeCommand。

DelegateCommand

DelegateCommand封装了两个委托:Execute和CanExecute,应用如下:

// view<Button Command="{Binding ExecuteDelegateCommand}" Content="DelegateCommand"/>// viewmodelpublic 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实例)<Button Content="Save" Command="{Binding ApplicationCommands.SaveCommand}"/>

EventAggregator

EventAggregator是一种事件机制,解决了松耦合模块间的通信问题。应用办法如下:

// Project.core中申明事件类型public class MessageSentEvent : PubSubEvent<string>{}// viewmodel中公布事件IEventAggregator _ea;public MessageViewModel(IEventAggregator ea){    _ea = ea;    // 公布事件的命令    SendMessageCommand = new DelegateCommand(SendMessage);}private void SendMessage(){    _ea.GetEvent<MessageSentEvent>().Publish(Message);}// viewmodel中订阅事件IEventAggregator _ea;public MessageListViewModel(IEventAggregator ea){    _ea = ea;    _ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);    // 如下形式能够过滤事件,可通过第二个参数指定解决线程    // _ea.GetEvent<MessageSentEvent>().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<ViewA>();}// xaml导航命令<Button Command="{Binding NavigateCommand}" CommandParameter="ViewA" >Navigate to View A</Button>// viewmodel实现导航public DelegateCommand<string> NavigateCommand { get; private set; }public MainWindowViewModel(IRegionManager regionManager){    _regionManager = regionManager;    NavigateCommand = new DelegateCommand<string>(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<bool> 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,能够实现向前/向后导航。示例如下:

// GoForwardpublic 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;    }}// GoBackpublic 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<ListBox ItemsSource="{Binding Items}" SelectionMode="Single">    <i:Interaction.Triggers>        <i:EventTrigger EventName="SelectionChanged">            <prism:InvokeCommandAction Command="{Binding SelectedCommand}"                 TriggerParameterPath="AddedItems" />        </i:EventTrigger>    </i:Interaction.Triggers></ListBox>// viewmodelpublic DelegateCommand<object[]> SelectedCommand { get; private set; }public MainWindowViewModel(){    ...    SelectedCommand = new DelegateCommand<object[]>(OnItemSelected);}private void OnItemSelected(object[] selectedItems){    if (selectedItems != null && selectedItems.Count() > 0)        SelectedItemText = selectedItems.FirstOrDefault().ToString();}