我正在开展一个项目,我正在使用Prof MVVM架构和Autofac,试图创建一个可供其他视图使用的通用页脚导航栏。
我试图将一个特定的绑定上下文从View的代码隐藏设置为ViewModel - 但是由于viewmodel的实例化需要依赖注入导航服务而无法这样做。 / p>
我有以下内容:
我通过执行以下操作插入局部视图:
<ContentPage
...
xmlns:pages="clr-namespace:MyProject.Views;assembly=Myproject"
.../>
<Layout
...
<pages:NavigationBarPage />
...
</Layout>
我的代码隐藏中的构造函数也是这样的:
public CodeBehindConstructor() {
BindingContext = new NavigationBarViewModel(requires
navigationservice);
}
如果我可以在NavigationBarView后面的代码中创建一个INavigationService实例,那将是可以解决的,但是我还没有找到办法这样做。
我的ViewModel构造函数如下所示:
public NavigationBarViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
...
...
}
_navigationService设置为未初始化的INavigationService,这使服务无法使用。
NavigationBarView和NavigationBarViewModel之间的绑定有效,但我无法弄清楚如何处理INavigationService的依赖注入。
答案 0 :(得分:0)
首先,只要保持与任何其他视图一样的约定,就可以自动浏览ViewModel。遇到问题的地方是,Prism目前还不支持将NavigationService注入到自定义视图的ViewModel中。 Xamarin Forms中的导航取决于您对要导航的页面的理解。简单地解决INavigationService
会导致NavigationService没有导航的网页概念,并且会完全搞乱导航。
首先,您要注意PrismApplication中的ConfigureViewModelLocator方法。您会注意到默认情况下Prism只处理一个视图&#39;对象是一个页面。您将要更新此处理以处理它是一个视图的情况,然后您可以走向ParentView,直到您到达作为Page的Parent。
protected override void ConfigureViewModelLocator()
{
ViewModelLocationProvider.SetDefaultViewModelFactory((view, type) =>
{
NamedParameter parameter = null;
switch(view)
{
case Page page:
parameter = new NamedParameter("navigationService", CreateNavigationService(page));
break;
case View customView:
var page = GetPage(customView);
parameter = new NamedParameter("navigationService", CreateNavigationService(page));
break;
}
return Container.Resolve(type, parameter);
});
}
private Page GetPage(View view)
{
switch(view.ParentView)
{
case Page page:
return page;
case null:
return null;
default:
return GetPage(view.ParentView)
}
}
如果由于某种原因您没有遵循约定并且不想显式设置AutoWire属性,您可以执行以下操作:
ViewModelLocationProvider.Register(typeof(NavigationBarView).ToString(),
typeof(NavigationBarViewModel));
答案 1 :(得分:0)
只是更新这个问题,以防其他人偶然发现(如我所做的那样)。
Prism v7.x现在可以选择使用以下方式将XAML中的局部视图的视图模型连接到父页面: prism:ViewModelLocator.AutowirePartialView 属性。
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MyPartial">
<StackLayout>
<Label Text="Please wait...." IsVisible="{Binding IsSearchLabelVisible}"/>
</StackLayout>
</ContentView>
ViewModelLocationProvider.Register(typeof(MyPartial).ToString(), typeof(MyPartialViewModel));
...
xmlns:uc="clr-namespace:MyApp"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="MyApp.Views.HostPage"
x:Name="HostPageName"
Title="Input ISBN"
....
<uc:MyPartial prism:ViewModelLocator.AutowirePartialView="{x:Reference HostPageName}"/>
这会将分部与宿主页连接起来,因此可以将分部的viewmodel声明为ContentPage类型 因此可以实例化所有常用的页面服务,例如navigationService和eventAggregator。
public class MyPartialViewModel : BaseViewModel
...
public bool IsSearchLabelVisible {get; set;}
public MyPartialViewModel(INavigationService navigationService,
IEventAggregator eventAgregatorService,
IPageDialogService dialogService)
: base(navigationService, eventAgregatorService)
...
此AutoWirePartialView with prism does not work or badly used?的链接 让我走上正确的路。
答案 2 :(得分:-1)
我在Xamarin.Forms应用程序中做了什么: *创建一个位于Application类中的静态容器(始终是XF的Application类的后代)。
public class BaseApplication : Application
{
public static IContainer Container { get; set; }
...
...
}
public BaseApplication(ContainerBuilder builder)
{
... register all dependencies here ... (don't forget your navigation service)
Container = builder.Build();
}
此课程由您的MainActivity(Android),MainPage(UWP)等创建。
LoadApplication(new BaseApplication(_containerBuilder));
当您需要从视图中创建视图模型时,您只需要
BindingContext = BaseApplication.Container.Resolve<MyViewModel>();