十年河東,十年河西,莫欺少年窮
學無止境,精益求精
1、新建項目wpfApp5,添加Nuget引用,並初始化App.xaml 及 cs 類
app.xaml 如下:
<Prism:PrismApplication x:Class="WpfApp5.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp5" xmlns:Prism="http://prismlibrary.com/" > <Application.Resources> </Application.Resources> </Prism:PrismApplication>
cs 類如下:
using DryIoc; using Prism.DryIoc; using Prism.Ioc; using Prism.Modularity; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; using WpfApp5.UserControls; using WpfApp5.UserControls.Models; using WpfApp5.Views; namespace WpfApp5 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { //設置啓動窗體爲MainView return Container.Resolve<MainView>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<viewA, viewAModel>();////如果不聲明名字爲viewA , 默認和類名一致 containerRegistry.RegisterForNavigation<viewB, viewBModel>("viewB");////如果不聲明名字爲viewB , 默認和類名一致 containerRegistry.RegisterForNavigation<viewC, viewCModel>();////如果不聲明名字爲viewC , 默認和類名一致 } } }
說明:
xaml 中引入 Prism
xmlns:Prism="http://prismlibrary.com/"
更改標籤爲:
<Prism:PrismApplication> 。。。。。。 </Prism:PrismApplication>
設置啓動窗體爲 MainView,這裏需要說明的是:窗體必須放在Views文件夾下而且必須以View結尾,ViewModel必須放在ViewModels文件夾下面,文件必須以ViewModel結尾。
App.xaml.cs 中註冊了三個導航窗體(用戶控件),分別爲:viewA、viewB、viewC,及啓動窗體MainView
2、聲明 MainView
新建文件夾 Views 和 數據上下文文件夾 ViewModels,在Views文件夾中新建 MainView窗體(必須以View結尾),在ViewModels文件夾中新建 MainViewModel 上下文類(必須以Model結尾)
MainView.xaml 如下
<Window x:Class="WpfApp5.Views.MainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp5.Views" xmlns:Prism="http://prismlibrary.com/" Prism:ViewModelLocator.AutoWireViewModel="True" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <Button Content="viewA" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewA"></Button> <Button Content="viewB" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewB"></Button> <Button Content="viewC" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewC"></Button> <Button Content="返回上一頁" Margin="5" Height="35" Width="100" Command="{Binding BtnBack}"></Button> <Button Content="返回下一頁" Margin="5" Height="35" Width="100" Command="{Binding BtnForward}"></Button> </StackPanel> <ContentControl Grid.Row="1" Prism:RegionManager.RegionName="ContentRegion"/> </Grid> </Window>
viewModel 類如下
public class MainViewModel : BindableBase { public DelegateCommand<string> BtnCommand { get; private set; } public DelegateCommand BtnBack { get; private set; } public DelegateCommand BtnForward { get; private set; } /// <summary> /// 區域管理器-跳轉相關 /// </summary> private readonly IRegionManager regionManager; /// <summary> /// 用於保存路由跳轉記錄 /// </summary> private IRegionNavigationJournal journal; public MainViewModel(IRegionManager regionManager) { BtnCommand = new DelegateCommand<string>(BtnRedirect); BtnBack = new DelegateCommand(Back); BtnForward = new DelegateCommand(Forward); this.regionManager = regionManager; } /// <summary> /// 頁面跳轉 /// </summary> /// <param name="parma"></param> private void BtnRedirect(string parma) { NavigationParameters keys = new NavigationParameters(); keys.Add("name", "河南大學"); keys.Add("id", "58"); regionManager.Regions["ContentRegion"].RequestNavigate(parma,navigationCallback, keys); } private void navigationCallback(NavigationResult navigation) { if (navigation.Result.Value) { //如果跳轉成功,則存儲跳轉記錄 journal = navigation.Context.NavigationService.Journal; } } /// <summary> /// 返回上一頁 /// </summary> private void Back() { if (journal.CanGoBack) { journal.GoBack(); } } /// <summary> /// 返回下一頁 /// </summary> private void Forward() { if (journal.CanGoForward) { journal.GoForward(); } } }
說明如下:
必須繼承自 BindableBase
public class MainViewModel : BindableBase
聲明按鈕命令事件、區域管理、路由
public DelegateCommand<string> BtnCommand { get; private set; } public DelegateCommand BtnBack { get; private set; } public DelegateCommand BtnForward { get; private set; } /// <summary> /// 區域管理器-跳轉相關 /// </summary> private readonly IRegionManager regionManager; /// <summary> /// 用於保存路由跳轉記錄 /// </summary> private IRegionNavigationJournal journal; public MainViewModel(IRegionManager regionManager) { BtnCommand = new DelegateCommand<string>(BtnRedirect); BtnBack = new DelegateCommand(Back); BtnForward = new DelegateCommand(Forward); this.regionManager = regionManager; }
帶有參數的頁面跳轉如下:
/// <summary> /// 頁面跳轉-帶有參數 /// </summary> /// <param name="parma"></param> private void BtnRedirect(string parma) { NavigationParameters keys = new NavigationParameters(); keys.Add("name", "河南大學"); keys.Add("id", "58"); regionManager.Regions["ContentRegion"].RequestNavigate(parma,navigationCallback, keys); } private void navigationCallback(NavigationResult navigation) { if (navigation.Result.Value) { //如果跳轉成功,則存儲跳轉記錄 journal = navigation.Context.NavigationService.Journal; } }
navigationCallback 爲回調事件,用於記錄導航
返回上一頁、下一頁代碼如下:
/// <summary> /// 返回上一頁 /// </summary> private void Back() { if (journal.CanGoBack) { journal.GoBack(); } } /// <summary> /// 返回下一頁 /// </summary> private void Forward() { if (journal.CanGoForward) { journal.GoForward(); } }
3、用戶控件 viewA (無需遵守Prism的規則)
xaml 如下:
<UserControl x:Class="WpfApp5.UserControls.viewA" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WpfApp5.UserControls" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <StackPanel Orientation="Vertical"> <TextBlock Text="I am viewA" FontSize="24"/> <TextBlock Text="{Binding Name}" FontSize="24"/> <TextBlock Text="{Binding Id}" FontSize="24"/> </StackPanel> </Grid> </UserControl>
綁定的Name 和 Id 爲參數傳遞的值
viewModel類如下:
public class viewAModel : BindableBase, INavigationAware, IConfirmNavigationRequest { public viewAModel() { } private string name; public string Name { get { return this.name; } set { name = value; RaisePropertyChanged(); } } private string id; public string Id { get { return this.id; } set { id = value; RaisePropertyChanged(); } } /// <summary> /// 路由保衛--可以在此方法中判斷是否允許跳轉--continuationCallback 會通知 OnNavigatedFrom 方法是否跳轉 /// </summary> /// <param name="navigationContext"></param> public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback) { var isok = false; if (MessageBox.Show("確定跳轉嗎", "溫馨提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { isok = true; } continuationCallback(isok); } /// <summary> /// 進入該viewModel時,是否創建新的viewModel對象 /// </summary> /// <param name="navigationContext"></param> /// <returns></returns> public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } /// <summary> /// 離開該viewModel執行 和 路由保衛配合使用 /// </summary> /// <param name="navigationContext"></param> public void OnNavigatedFrom(NavigationContext navigationContext) { //離開時 可能會涉及到一些數據處理,在此不做演示 } /// <summary> /// 進入該viewModel時執行 /// </summary> /// <param name="navigationContext"></param> public void OnNavigatedTo(NavigationContext navigationContext) { if (navigationContext.Parameters.ContainsKey("name")) { this.Name = navigationContext.Parameters.GetValue<string>("name"); } if (navigationContext.Parameters.ContainsKey("id")) { this.Id = navigationContext.Parameters.GetValue<string>("id"); } } }
說明如下:
繼承自 BindableBase,INavigationAware, IConfirmNavigationRequest
public class viewAModel : BindableBase, INavigationAware, IConfirmNavigationRequest
BindableBase(用於雙向綁定),INavigationAware(用於導航跳轉), IConfirmNavigationRequest(用於導航跳轉前,確認是否跳轉,即路由保衛)
1、進入用戶控件viewModel時執行
/// <summary> /// 進入該viewModel時執行 /// </summary> /// <param name="navigationContext"></param> public void OnNavigatedTo(NavigationContext navigationContext) { if (navigationContext.Parameters.ContainsKey("name")) { this.Name = navigationContext.Parameters.GetValue<string>("name"); } if (navigationContext.Parameters.ContainsKey("id")) { this.Id = navigationContext.Parameters.GetValue<string>("id"); } }
這裏我們判斷URL是否含有相關參數,有的話,則接收,賦值
2、進入該viewModel時,是否重新創建該viewmodle對象
/// <summary> /// 進入該viewModel時,是否創建新的viewModel對象 /// </summary> /// <param name="navigationContext"></param> /// <returns></returns> public bool IsNavigationTarget(NavigationContext navigationContext) { return true; }
3、離開viewMdoel時
/// <summary> /// 離開該viewModel執行 和 路由保衛配合使用 /// </summary> /// <param name="navigationContext"></param> public void OnNavigatedFrom(NavigationContext navigationContext) { //離開時 可能會涉及到一些數據處理,在此不做演示 } /// <summary> /// 路由保衛--可以在此方法中判斷是否允許跳轉--continuationCallback 會通知 OnNavigatedFrom 方法是否跳轉 /// </summary> /// <param name="navigationContext"></param> public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback) { var isok = false; if (MessageBox.Show("確定跳轉嗎", "溫馨提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { isok = true; } continuationCallback(isok); }
ConfirmNavigationRequest 可以理解爲路由保衛,用於判斷是否可以跳轉, continuationCallback 爲回調函數,當它的參數爲true時,則允許跳轉,否則不跳轉。
4、雙向綁定
private string name; public string Name { get { return this.name; } set { name = value; RaisePropertyChanged(); } } private string id; public string Id { get { return this.id; } set { id = value; RaisePropertyChanged(); } }
注意使用 RaisePropertyChanged();方法即可
@天才臥龍的博客