Prism导航
注册导航页面
注册区域
使用p:RegionManager.RegionName注册页面区域
<Window x:Class="WpfApp1.NavigationWindow" 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:local="clr-namespace:WpfApp1" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:p="http://prismlibrary.com/" Title="NavigationWindow" Width="800" Height="450" mc:Ignorable="d"> <DockPanel> <Grid Width="220" DockPanel.Dock="Left"> <StackPanel> <Button Margin="0,3" Command="{Binding OpenViewCommand}" CommandParameter="ViewA" Content="View A" /> <Button Margin="0,3" Command="{Binding OpenViewCommand}" CommandParameter="ViewB" Content="View B" /> <Button Margin="0,3" Content="View C" /> </StackPanel> </Grid> <Grid> <!--<ContentControl p:RegionManager.RegionName="ViewRegion"/>--> <TabControl p:RegionManager.RegionName="ViewRegion"> <TabControl.ItemContainerStyle> <Style TargetType="TabItem"> <!-- TabItem的绑定数据源是页面对象 --> <!-- TabItem的DataContext=View对象 --> <!-- View对象的DataContext=对应的ViewModel --> <Setter Property="Header" Value="{Binding DataContext.Title}" /> </Style> </TabControl.ItemContainerStyle> </TabControl> </Grid> </DockPanel> </Window>
public class NavigationWindowVewModel { public ICommand OpenViewCommand { get; set; } // 区域管理,需要拿到RegionManager IRegionManager _regionManager; public NavigationWindowVewModel(IRegionManager regionManager) { _regionManager = regionManager; OpenViewCommand = new DelegateCommand<string>(DoOpenView); } private void DoOpenView(string viewName) { _regionManager.RegisterViewWithRegion("ViewRegion", viewName); } }
public class Startup : PrismBootstrapper { protected override DependencyObject CreateShell() { return Container.Resolve<NavigationWindow>(); //return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<ViewA>(); containerRegistry.RegisterForNavigation<ViewB>(); } protected override void ConfigureViewModelLocator() { base.ConfigureViewModelLocator(); ViewModelLocationProvider.Register(typeof(NavigationWindow).ToString(), typeof(NavigationWindowVewModel)); } }
<UserControl x:Class="WpfApp1.Views.ViewA" 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:local="clr-namespace:WpfApp1.Views" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> <StackPanel> <TextBox FontSize="20" Foreground="Orange" Text="View A" /> <TextBlock FontSize="20" Foreground="Red" Text="{Binding Title}" /> <Button Command="{Binding CloseTabCommand}" Content="Close" /> </StackPanel> </UserControl>
<UserControl x:Class="WpfApp1.Views.ViewB" 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:local="clr-namespace:WpfApp1.Views" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> <Grid> <TextBlock FontSize="20" Foreground="Green" Text="View B" /> </Grid> </UserControl>
public class ViewAViewModel { public string Title { get; set; } = "View A"; public ICommand CloseTabCommand { get; set; } IRegionManager _regionManager; public ViewAViewModel(IRegionManager regionManager) { _regionManager = regionManager; CloseTabCommand = new DelegateCommand(DoCloseTab); } private void DoCloseTab() { } }
public class ViewBViewModel { public string Title { get; set; } = "View B"; public ICommand CloseTabCommand { get; set; } IRegionManager _regionManager; public ViewBViewModel(IRegionManager regionManager) { _regionManager = regionManager; CloseTabCommand = new DelegateCommand(DoCloseTab); } private void DoCloseTab() { } }
导航页面传参——INavigationAware接口
public class ViewAViewModel : INavigationAware { public string Title { get; set; } = "View A"; public ICommand CloseTabCommand { get; set; } IRegionManager _regionManager; public ViewAViewModel(IRegionManager regionManager) { _regionManager = regionManager; CloseTabCommand = new DelegateCommand(DoCloseTab); } private void DoCloseTab() { } #region INavigationAware接口方法 public bool IsNavigationTarget(NavigationContext navigationContext) { // 是否允许重复导航进来 // 主-》A-》B-》A (显示前对象) 返回True // 主-》A-》B-》A(新对象) 返回false return true; // 编辑页面,通过主页的子项点击,打开这个页面, // 子项有很多,可能同时打开多个子项进行编辑 } public void OnNavigatedFrom(NavigationContext navigationContext) { // 从当前View导航出去的时候触发 // 从某个页面跳转到另一个页面的时候,可以把这个信息带过去 navigationContext.Parameters.Add("abcd", "Hello ViewA"); } public void OnNavigatedTo(NavigationContext navigationContext) { // 打开当前View的时候触发 string arg = navigationContext.Parameters.GetValue<string>("abcd"); } #endregion }
public class NavigationWindowVewModel { public ICommand OpenViewCommand { get; set; } // 区域管理,需要拿到RegionManager IRegionManager _regionManager; public NavigationWindowVewModel(IRegionManager regionManager) { _regionManager = regionManager; OpenViewCommand = new DelegateCommand<string>(DoOpenView); } private void DoOpenView(string viewName) { //_regionManager.RegisterViewWithRegion("ViewRegion", viewName); // 向某个View中传递特定参数,参数对接到View的ViewModel里 if (viewName == "ViewA") { NavigationParameters parameters = new NavigationParameters(); parameters.Add("abcd", "Hello"); _regionManager.RequestNavigate("ViewRegion", viewName, parameters); } else if (viewName == "ViewB") _regionManager.RequestNavigate("ViewRegion", viewName); } }
自动销毁——IRegionMemberLifetime接口
页面的ViewModel继承IRegionMemberLifetime接口
接口中的KeepAlive参数默认为true:非激活状态,在Region中保留
public class ViewAViewModel : INavigationAware , IRegionMemberLifetime { public string Title { get; set; } = "View A"; public ICommand CloseTabCommand { get; set; } IRegionManager _regionManager; public ViewAViewModel(IRegionManager regionManager) { _regionManager = regionManager; CloseTabCommand = new DelegateCommand(DoCloseTab); } public bool KeepAlive => false; private void DoCloseTab() { } #region INavigationAware接口方法 public bool IsNavigationTarget(NavigationContext navigationContext) { // 是否允许重复导航进来 // 主-》A-》B-》A (显示前对象) 返回True // 主-》A-》B-》A(新对象) 返回false return true; // 编辑页面,通过主页的子项点击,打开这个页面, // 子项有很多,可能同时打开多个子项进行编辑 } public void OnNavigatedFrom(NavigationContext navigationContext) { // 从当前View导航出去的时候触发 // 从某个页面跳转到另一个页面的时候,可以把这个信息带过去 navigationContext.Parameters.Add("abcd", "Hello ViewA"); } public void OnNavigatedTo(NavigationContext navigationContext) { // 打开当前View的时候触发 string arg = navigationContext.Parameters.GetValue<string>("abcd"); } #endregion }
页面离开前的事件——IConfirmNavigationRequest接口
页面ViewModel实现IConfirmNavigationRequest接口
public class ViewAViewModel : INavigationAware,IRegionMemberLifetime,IConfirmNavigationRequest { public string Title { get; set; } = "View A"; public ICommand CloseTabCommand { get; set; } IRegionManager _regionManager; public ViewAViewModel(IRegionManager regionManager) { _regionManager = regionManager; CloseTabCommand = new DelegateCommand(DoCloseTab); } private void DoCloseTab() { } #region IRegionMemberLifetime接口方法 // 用来控制当前页面非激活状态,是否在Region中保留 public bool KeepAlive => true; #endregion #region INavigationAware接口方法 #region INavigationAware接口方法 public bool IsNavigationTarget(NavigationContext navigationContext) { // 是否允许重复导航进来 // 主-》A-》B-》A (显示前对象) 返回True // 主-》A-》B-》A(新对象) 返回false return true; // 编辑页面,通过主页的子项点击,打开这个页面, // 子项有很多,可能同时打开多个子项进行编辑 } public void OnNavigatedFrom(NavigationContext navigationContext) { // 从当前View导航出去的时候触发 // 从某个页面跳转到另一个页面的时候,可以把这个信息带过去 navigationContext.Parameters.Add("abcd", "Hello ViewA"); } public void OnNavigatedTo(NavigationContext navigationContext) { // 打开当前View的时候触发 string arg = navigationContext.Parameters.GetValue<string>("abcd"); } #endregion #region IConfirmNavigationRequest接口方法 // 当从当前页面跳转到另一个页面时触发 // OnNavigatedFrom调用前执行 public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback) { // 打开某个页面, if (MessageBox.Show("是否离开当前页面?", "导航提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { /// 继续打开 /// continuationCallback?.Invoke(true); } else // 不被导航 continuationCallback?.Invoke(false); } #endregion }
导航日志
编写测试程序
public class Startup : PrismBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<PrismRegion.Journal.Views.MainView>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<PrismRegion.Journal.Views.ViewA>();
containerRegistry.RegisterForNavigation<PrismRegion.Journal.Views.ViewB>();
containerRegistry.RegisterForNavigation<PrismRegion.Journal.Views.ViewC>();
}
}
public partial class App : Application
{
public App()
{
new Startup().Run();
}
}
<Window x:Class="Zhaoxi.PrismRegion.Journal.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:Zhaoxi.PrismRegion.Journal.Views"
xmlns:p="http://prismlibrary.com/"
mc:Ignorable="d"
Title="MainView" Height="450" Width="800">
<Grid>
<Button Content="Load Views" Command="{Binding BtnLoadCommand}"
VerticalAlignment="Top"/>
<ContentControl p:RegionManager.RegionName="MainRegion" Margin="0,30,0,0"/>
</Grid>
</Window>
public class MainViewModel
{
public DelegateCommand BtnLoadCommand { get; set; }
public MainViewModel(IRegionManager regionManager)
{
BtnLoadCommand = new DelegateCommand(() =>
{
regionManager.RequestNavigate("MainRegion", "ViewA");
});
}
}
<UserControl x:Class="Zhaoxi.PrismRegion.Journal.Views.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:Zhaoxi.PrismRegion.Journal.Views"
mc:Ignorable="d" FontSize="20"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel>
<TextBlock Text="View A" Foreground="Orange" />
<Button Content="向后" Command="{Binding GoBackCommand}"/>
<Button Content="向前" Command="{Binding ForwordCommand}"/>
</StackPanel>
</Grid>
</UserControl>
页面的ViewModel继承INavigationAware接口
在OnNavigatedTo方法中取出navigationContext.NavigationService.Journal
journal.GoBack()提供导航回退
public class ViewAViewModel : INavigationAware
{
public DelegateCommand GoBackCommand { get; set; }
public DelegateCommand ForwordCommand { get; set; }
IRegionNavigationJournal journal;
public ViewAViewModel(IRegionManager regionManager)
{
GoBackCommand = new DelegateCommand(() =>
{
if (journal.CanGoBack)
{
journal.GoBack();
}
});
ForwordCommand = new DelegateCommand(() =>
{
if (journal.CanGoForward)
{
journal.GoForward();
}
else
{
regionManager.RequestNavigate("MainRegion", "ViewB");
}
});
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
journal = navigationContext.NavigationService.Journal;
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
参照ViewA写ViewB和ViewC
修改对应ViewModel的GoBackCommand与ForwordCommand
public ViewBViewModel(IRegionManager regionManager)
{
GoBackCommand = new DelegateCommand(() =>
{
if (journal.CanGoBack)
{
journal.GoBack();
}
});
ForwordCommand = new DelegateCommand(() =>
{
if (journal.CanGoForward)
{
journal.GoForward();
}
else
{
regionManager.RequestNavigate("MainRegion", "ViewC");
}
});
}
public ViewCViewModel(IRegionManager regionManager)
{
GoBackCommand = new DelegateCommand(() =>
{
if (journal.CanGoBack)
{
journal.GoBack();
}
});
ForwordCommand = new DelegateCommand(() =>
{
if (journal.CanGoForward)
{
journal.GoForward();
}
});
}
运行后实现导航的前进后退
取消导航——IJournalAware
在ViewB的ViewModel中继承IJournalAware接口,并在实现方法中返回false。
public class ViewBViewModel : INavigationAware, IJournalAware
{
public DelegateCommand GoBackCommand { get; set; }
public DelegateCommand ForwordCommand { get; set; }
IRegionNavigationJournal journal;
public ViewBViewModel(IRegionManager regionManager)
{
GoBackCommand = new DelegateCommand(() =>
{
if (journal.CanGoBack)
{
journal.GoBack();
}
});
ForwordCommand = new DelegateCommand(() =>
{
if (journal.CanGoForward)
{
journal.GoForward();
}
else
{
regionManager.RequestNavigate("MainRegion", "ViewC");
}
});
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
journal = navigationContext.NavigationService.Journal;
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
// IJournalAware的方法实现
public bool PersistInHistory()
{
return false;
}
}
运行后,导航会取消ViewB的导航
来源:https://www.cnblogs.com/ZHIZRL/p/17883434.html