Prism(八) 导航
源码地址 - WineMonk/PrismStudy: Prism框架学习 (github.com)
导航基础
视图
ViewA/B.xaml
<UserControl x:Class="ModuleA.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<StackPanel>
<TextBlock Text="{Binding Title}" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Text="{Binding PageViews}" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</UserControl>
ViewA/BViewModel.cs
public class ViewAViewModel : BindableBase
{
public ViewAViewModel()
{
}
}
注册导航视图
public class ModuleAModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<ViewA>();
containerRegistry.RegisterForNavigation<ViewB>();
}
}
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<ModuleA.ModuleAModule>();
}
}
导航视图
MainWindow.xaml
<Window x:Class="BasicRegionNavigation.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">
<DockPanel LastChildFill="True">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5" >
<Button Command="{Binding NavigateCommand}" CommandParameter="ViewA" Margin="5">Navigate to View A</Button>
<Button Command="{Binding NavigateCommand}" CommandParameter="ViewB" Margin="5">Navigate to View B</Button>
</StackPanel>
<ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="5" />
</DockPanel>
</Window>
MainWindowViewModel.cs
public class MainWindowViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
private string _title = "Prism Unity Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
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);
}
}
导航视图请求回调
MainWindowViewModel.cs
public class MainWindowViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
private string _title = "Prism Unity Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
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);
_regionManager.RequestNavigate("ContentRegion", navigatePath, NavigationComplete);
}
/// <summary>
/// 导航请求回调方法
/// </summary>
/// <param name="result">导航结果</param>
private void NavigationComplete(NavigationResult result)
{
System.Windows.MessageBox.Show(String.Format("Navigation to {0} complete. ", result.Context.Uri));
}
}
视图察觉参与导航
ViewA/B.xaml
<UserControl x:Class="ModuleA.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<StackPanel>
<TextBlock Text="{Binding Title}" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Text="{Binding PageViews}" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</UserControl>
ViewA/BViewModel.cs
public class ViewAViewModel : BindableBase, INavigationAware
{
private string _title = "ViewA";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private int _pageViews;
public int PageViews
{
get { return _pageViews; }
set { SetProperty(ref _pageViews, value); }
}
public ViewAViewModel()
{
}
/// <summary>
/// 当实现者被导航到时调用。
/// </summary>
/// <param name="navigationContext">导航上下文</param>
public void OnNavigatedTo(NavigationContext navigationContext)
{
PageViews++;
}
/// <summary>
/// 调用以确定此实例是否可以处理导航请求。
/// </summary>
/// <param name="navigationContext">导航上下文</param>
/// <returns>如果这个实例接受导航请求,返回True;否则,False(将会导航至此视图的新实例)</returns>
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
/// <summary>
/// 当实现者被导航离开时调用。
/// </summary>
/// <param name="navigationContext">导航上下文</param>
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
通过参数导航
Model
Person.cs
public class Person : INotifyPropertyChanged
{
#region Properties
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged();
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
}
}
private int _age;
public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged();
}
}
private DateTime? _lastUpdated;
public DateTime? LastUpdated
{
get { return _lastUpdated; }
set
{
_lastUpdated = value;
OnPropertyChanged();
}
}
#endregion //Properties
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string propertyname = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
#endregion //INotifyPropertyChanged
public override string ToString()
{
return String.Format("{0}, {1}", LastName, FirstName);
}
}
View
PersonList.xaml
<UserControl
x:Class="ModuleA.Views.PersonList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding DataContext.SelectedPerson.FirstName}" />
</Style>
</UserControl.Resources>
<Grid
x:Name="LayoutRoot"
Margin="10"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox x:Name="_listOfPeople" ItemsSource="{Binding People}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<prism:InvokeCommandAction Command="{Binding PersonSelectedCommand}" CommandParameter="{Binding SelectedItem, ElementName=_listOfPeople}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<TabControl
Grid.Row="1"
Margin="10"
prism:RegionManager.RegionName="PersonDetailsRegion" />
</Grid>
</UserControl>
PersonDetail.xaml
<UserControl x:Class="ModuleA.Views.PersonDetail"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- First Name -->
<TextBlock Text="First Name:" Margin="5" />
<TextBlock Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.FirstName}" />
<!-- Last Name -->
<TextBlock Grid.Row="1" Text="Last Name:" Margin="5" />
<TextBlock Grid.Row="1" Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.LastName}" />
<!-- Age -->
<TextBlock Grid.Row="2" Text="Age:" Margin="5"/>
<TextBlock Grid.Row="2" Grid.Column="1" Margin="5" Text="{Binding SelectedPerson.Age}"/>
</Grid>
</UserControl>
ViewModel
PersonListViewModel.cs
using System;
using ModuleA.Business;
using Prism.Mvvm;
using Prism.Navigation.Regions;
namespace ModuleA.ViewModels
{
public class PersonDetailViewModel : BindableBase, INavigationAware
{
private Person _selectedPerson;
public Person SelectedPerson
{
get { return _selectedPerson; }
set { SetProperty(ref _selectedPerson, value); }
}
public PersonDetailViewModel()
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
var person = navigationContext.Parameters["person"] as Person;
if (person != null)
SelectedPerson = person;
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
var person = navigationContext.Parameters["person"] as Person;
if (person != null)
return SelectedPerson != null && SelectedPerson.LastName == person.LastName;
else
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
}
PersonDetailViewModel.cs
using ModuleA.Business;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation.Regions;
using System;
using System.Collections.ObjectModel;
namespace ModuleA.ViewModels
{
public class PersonListViewModel : BindableBase
{
IRegionManager _regionManager;
private ObservableCollection<Person> _people;
public ObservableCollection<Person> People
{
get { return _people; }
set { SetProperty(ref _people, value); }
}
public DelegateCommand<Person> PersonSelectedCommand { get; private set; }
public PersonListViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
PersonSelectedCommand = new DelegateCommand<Person>(PersonSelected);
CreatePeople();
}
private void PersonSelected(Person person)
{
var parameters = new NavigationParameters();
parameters.Add("person", person);
if (person != null)
__regionManager.RequestNavigate("PersonDetailsRegion", typeof(PersonDetail).Name, parameters);
}
private void CreatePeople()
{
var people = new ObservableCollection<Person>();
for (int i = 0; i < 10; i++)
{
people.Add(new Person()
{
FirstName = String.Format("First {0}", i),
LastName = String.Format("Last {0}", i),
Age = i
});
}
People = people;
}
}
}
导航请求处理
ViewA/BViewModel.cs
public class ViewAViewModel : BindableBase, IConfirmNavigationRequest
{
public ViewAViewModel()
{
}
/// <summary>
/// 确定此实例是否接受导航。
/// </summary>
/// <param name="navigationContext">导航上下文</param>
/// <param name="continuationCallback">指示导航何时可以继续的回调函数。</param>
/// <remarks>
/// 此方法的实现者在此方法完成之前不需要调用回调函数,但它们必须确保回调函数最终被调用。
/// </remarks>
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)
{
}
}