本文參考Prism官方示例git
Prism提供了兩種命令:DelegateCommand和CompositeCommand。github
DelegateCommand封裝了兩個委託:Execute和CanExecute,使用以下:app
// view <Button Command="{Binding ExecuteDelegateCommand}" Content="DelegateCommand"/> // 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時,將依次調用每一個子命令。默認狀況下,當全部子命令CanExecute均返回true時纔會執行CompositeCommand。使用方法以下:ide
// 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是一種事件機制,解決了鬆耦合模塊間的通訊問題。使用方法以下:函數
// 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 }
區別於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接口包含三個方法:OnNavigatedFrom、OnNavigatedTo、IsNavigationTarge。當ViewAViewModel及ViewBViewModel均實現了INavigationAware接口,ViewA導航到ViewB時,先調用ViewA的OnNavigatedFrom方法,而後調用ViewB的IsNavigationTarge,當其返回true時,調用OnNavigatedTo方法,若IsNavigationTarge返回false,建立新ViewB。示例以下:code
public class ViewAViewModel : BindableBase, INavigationAware { public void OnNavigatedTo(NavigationContext navigationContext) { // ... } public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } public void OnNavigatedFrom(NavigationContext navigationContext) { // ... } }
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接口只包含一個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能夠記錄導航的過程,其經過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(); } }
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> // viewmodel public 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(); }