05Prism WPF 入门实战 - Navigation
1.概要
源码及PPT地址:https://github.com/JusterZhu/wemail
视频地址:https://www.bilibili.com/video/BV1KQ4y1C7tg?share\source=copy\web
本章分为以下三个部分来了解:
Part1 视图导航、参数传递
Part2 确认导航
Part3 导航日志
2.详细内容
Part1 视图导航、参数传递
当用户与丰富的客户端应用程序交互时,其用户界面 (UI) 将不断更新,以反映用户正在处理的当前任务和数据。随着时间的推移,随着用户与应用程序内的交互并完成各种任务,UI 可能会发生相当大的变化。应用程序协调这些 UI 更改的过程通常称为导航,这一过程由INavigationAware做支撑。
应用场景:View之间传值、需要在导航过程做操作(例如及时释放资源)。
public class ContactViewModel : BindableBase , INavigationAware
{
private ObservableCollection<string> _contacts;
private string _message;
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public ObservableCollection<string> Contacts
{
get => _contacts ?? (_contacts = new ObservableCollection<string>());
}
public ContactViewModel()
{
Message = "Wemail.Contact Prism Module";
Contacts.Add("联系人张某");
Contacts.Add("联系人王某");
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
var parameter = navigationContext.Parameters["Contact"];
if (parameter == null) return;
//导航到当前页面前, 此处可以传递过来的参数以及是否允许导航等动作的控制
Debug.WriteLine(parameter.ToString() + "To Contact View.");
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//根据业务需要调整该视图,是否创建新示例。为true的时候表示不创建新实例,页面还是之前的;
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
//导航离开当前页面前。
Debug.WriteLine("Leave Contact View.");
}
}
Part2 确认导航
您经常会发现您需要在导航操作期间与用户进行交互,以便用户可以确认或取消它。例如,在许多应用程序中,用户可能会尝试在输入或编辑数据时进行导航。在这些情况下,您可能需要询问用户是否希望保存或丢弃在继续从页面中导航之前已输入的数据,或者用户是否希望完全取消导航操作。这些特性由IConfirmNavigationRequest做支撑,它融入了AOP(面向切面编程)的思想。
应用场景:权限管理、检测用户行为(页面停留多久、哪个模块访问次数最多等)、日志记录等。
public class TempViewAViewModel : IConfirmNavigationRequest
{
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
bool result = true;
// this is demo code only and not suitable for production. It is generally
// poor practice to reference your UI in the view model. Use the Prism
// IDialogService to help with this.
if (MessageBox.Show("Do you to navigate?", "Navigate?", MessageBoxButton.YesNo) == MessageBoxResult.No)
result = false;
continuationCallback(result);
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//是否创建新示例。为true的时候表示不创建新示例,页面还是之前的;如果为false,则创建新的页面。
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
//导航离开当前页面前。
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
//导航到当前页面前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
}
}
Part3 导航日志
导航日志其实就是对导航系统的一个管理功能,理论上来说,我们应该知道我们上一步导航的位置、以及下一步导航的位置,包括我们导航的历史记录。以便于我们使用导航对应用程序可以灵活的控制。类似于我们熟知的双向链表结构。导航日志由IRegionNavigationJournal提供支撑。
IRegionNavigationJournal接口有如下功能:
GoBack() : 返回上一页
CanGoBack: 是否可以返回上一页
GoForward(): 返回后一页
CanGoForward: 是否可以返回后一页
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
//Region管理对象
private IRegionManager _regionManager;
private IModuleCatalog _moduleCatalog;
private ObservableCollection<IModuleInfo> _modules;
private DelegateCommand _loadModulesCommand;
private DelegateCommand _openViewA;
private DelegateCommand _openViewB;
private DelegateCommand _goBackView;
private DelegateCommand _goForwardView;
private IModuleInfo _moduleInfo;
//导航日志
private IRegionNavigationJournal _navigationJournal;
public IView View { get; set; }
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public ObservableCollection<IModuleInfo> Modules
{
get => _modules ?? (_modules = new ObservableCollection<IModuleInfo>());
}
public DelegateCommand LoadModulesCommand { get => _loadModulesCommand = new DelegateCommand(InitModules); }
public IModuleInfo ModuleInfo
{
get
{
return _moduleInfo;
}
set
{
_moduleInfo = value;
Navigate(value);
}
}
public DelegateCommand OpenViewA
{
get => _openViewA ?? (_openViewA = new DelegateCommand(OpenViewAAction));
}
public DelegateCommand OpenViewB
{
get => _openViewB ?? (_openViewB = new DelegateCommand(OpenViewBAction));
}
public DelegateCommand GoBackView { get => _goBackView ?? (_goBackView = new DelegateCommand(GoBackViewAction)); }
public DelegateCommand GoForwardView { get => _goForwardView ?? (_goForwardView = new DelegateCommand(GoForwardViewAction)); }
public MainWindowViewModel(IRegionManager regionManager, IModuleCatalog moduleCatalog)
{
_regionManager = regionManager;
_moduleCatalog = moduleCatalog;
}
private void OpenViewAAction()
{
//_regionManager.RequestNavigate("ContentRegion", "TempViewA");
_regionManager.RequestNavigate(