@AdamVincent 发布的链接和“缺失”方法对于使用 ViewModelLocationProvider 的普通视图/视图模型导航非常有用。但是,当尝试将两个视图模型用于同一视图时,它们不起作用。这是因为在扩展方法内部有一个调用将视图模型注册到视图以供 ViewModelLocationProvider 使用。
private static IUnityContainer RegisterTypeForNavigationWithViewModel<TViewModel>(this IUnityContainer container, Type viewType, string name)
{
if (string.IsNullOrWhiteSpace(name))
name = viewType.Name;
ViewModelLocationProvider.Register(viewType.ToString(), typeof(TViewModel));
return container.RegisterTypeForNavigation(viewType, name);
}
在内部,ViewModelLocationProvider.Register 使用字典来存储视图模型和视图之间的关联。这意味着,当您将两个视图模型注册到同一个视图时,第二个将覆盖第一个。
Container.RegisterTypeForNavigation<PageA, ViewModelA>("PageA1");
Container.RegisterTypeForNavigation<PageA, ViewModelB>("PageA2");
所以通过上述方法,当使用 ViewModelLocationProvider 时,它总是会创建一个 ViewModelB 的实例,因为它是最后一个被注册的。
另外,下一行调用RegisterTypeForNavigation,它本身最终调用Container.RegisterType,只是传递viewType。
为了解决这个问题,我使用 Injection 属性以不同的方式解决了这个问题。我有以下方法将我的视图模型绑定到我的视图
private void BindViewModelToView<TView,TViewModel>(string name)
{
if (!Container.IsRegistered<TViewModel>())
{
Container.RegisterType<TViewModel>();
}
Container.RegisterType<TView, TViewModel>(name,new InjectionProperty("DataContext", new ResolvedParameter<TViewModel>()));
}
我们知道每个视图都会有一个 DataContext 属性,因此 Injection 属性会将视图模型直接注入到视图的 DataContect 中。
注册视图模型时,您将使用以下调用,而不是使用 RegisterTypeForNavigation:
BindViewModelToView<PageA,ViewModelA>("ViewModelA");
BindViewModelToView<PageA,ViewModelB>("ViewModelB");
为了创建视图,我已经有了一个方法,用于将适当的视图注入我的区域,它使用视图名称作为获取正确视图模型实例的键。
private object LoadViewIntoRegion<TViewType>(IRegion region, string name)
{
object view = region.GetView(name);
if (view == null)
{
view = _container.Resolve<TViewType>(name);
if (view is null)
{
view = _container.Resolve<TViewType>();
}
region.Add(view, name);
}
return view;
}
我只是用
调用
var view = LoadViewintoRegion<PageA>(region,"ViewModelA");
和
var view = LoadViewintoRegion<PageA>(region,"ViewModelB");
所以对于普通的单个视图/视图模型,我使用 ViewModelLocationProvider.AutoWireViewModel 属性,而我有多个视图模型,我使用这种替代方法。