简单导航2
简单
- 不借用字符串去定位 ContentControl;
- 注册视图时同时注册视图名-视图的关系,这样可以直接使用视图名进行导航;
导航
- 使用的是 MSDI;
- 在 viewModel 中绑定 ContentControl 的 Content 属性;
- 依赖
CommunityToolkit.Mvvm 进行消息通知;
- 通过视图名称查找视图实例;
注册
public static class DependencyInjectionExtensions
{
public static IHostBuilder ConfigureViews(this IHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices(
(sc) =>
{
sc.AddSingleton<MainWindow>();
sc.AddSingleton<MainViewModel>();
// navigation
sc.AddForNavigation(typeof(VisibilityView), typeof(VisibilityViewModel));
sc.AddForNavigation(typeof(GridSplitterView), typeof(GridSplitterViewModel));
sc.AddForNavigation(typeof(CustomizedTabItemView), typeof(CustomizedTabItemViewModel));
sc.AddForNavigation(typeof(MessageBoxView), typeof(MessageBoxViewModel));
sc.AddForNavigation(typeof(DragDropView), typeof(DragDropViewModel));
sc.AddForNavigation(typeof(ProgressMaskView), typeof(ProgressMaskViewModel));
sc.AddForNavigation(typeof(DesignTimeDataView), typeof(DesignTimeDataViewModel));
sc.AddForNavigation(typeof(ValidationView), typeof(ValidationViewModel));
sc.AddForNavigation(typeof(PlayerView), typeof(PlayerViewModel));
}
);
}
public static void AddForNavigation(this IServiceCollection sc, Type view, Type viewModel)
{
var viewItem = new ViewRegistryItem()
{
Name = view.Name,
ViewType = view,
ViewModelType = viewModel
};
sc.AddSingleton(viewItem);
sc.AddTransient(view);
sc.AddTransient(viewModel);
}
}
发出导航请求
partial void OnSelectedViewChanged(ViewItem? value)
{
if (value is null)
{
return;
}
Messenger.Send(value.ViewName, Channels.NAVIGATION);
}
处理导航请求
private void Navigate(string viewName)
{
var views = this.serviceProvider.GetService<IEnumerable<ViewRegistryItem>>();
var viewItem = views?.LastOrDefault(v => v.Name == viewName);
if (viewItem is null)
{
return;
}
var view = this.serviceProvider.GetService(viewItem.ViewType);
if (view is null)
{
return;
}
ContentView = view;
}
总结
- 可以使用字符串来避免导航时需要视图类型的耦合;
- 在视图注册了的情况下,后续新增导航视图时只需,1. 添加导航目录;2. 发送请求导航消息;
- 如何导航嵌套得很深的话,在多个 viewModel 中可能会重复实现相似的逻辑,考虑创建导航管理类,将导航的职责提取出来;
Ref
Github: orrest/Tests