我正在使用一个具有两个完全独立的视图模型的视图。
例如,您可以考虑使用通用列表视图在某处显示苹果,而在其他地方显示汽车。没关系。
在Xamarin的Prism.Forms中,无法使用这样的viewModel粘合视图。
Container.RegisterTypeForNavigation<PageA, ViewModelA>("PageA1");
Container.RegisterTypeForNavigation<PageA, ViewModelB>("PageA2");
我找不到Prism WPF中的等效项,有人可以帮助我吗?
答案 0 :(得分:1)
@AdamVincent发布的链接和“ missing”方法对于使用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");
要创建视图,我已经有一种方法可以用来将适当的视图注入到我的区域中,并且可以使用viewname作为键来获取正确的viewmodel实例。
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");
因此,对于普通的单个View / Viewmodel,我使用ViewModelLocationProvider.AutoWireViewModel属性,在有多个ViewModel的地方,我使用这种替代方法。