带 Xamarin.Forms 的棱镜 - 如何自动装配另一个 ContentView 内的 ContentView
Prism with Xamarin.Forms - how to autowire ContentView which is inside another ContentView
当 ContentView 直接包含在页面中时,我们成功地将 ContentView 连接到它们的 ViewModel,使用 XAML 如:
<local:AwesomeView mvvm:ViewModelLocator.AutowirePartialView=”{x:Reference self}” />
其中 self 是父页面。
但是,我们有包含 ContentView 的 ContentView,并且如上所述对嵌套视图使用 AutoWirePartialView 不起作用。 ContentViews 没有连接到他们的 ViewModels。
查看 Prism 代码:
- AutoWirePartialView 有评论 "This API is Obsolete and will
在 8.0 预览期间被删除
- 属性 更改了 AutoWirePartialView 的处理程序明确检查父级是否为 Page,因此不能与父级 ContentView
一起使用
所以从 Prism 代码中可以很清楚地看出为什么这行不通!
有没有办法用 Prism 实现这一点?
版本:
Xamarin.Forms - 4.4.0.991265
棱镜 - 7.1.0.431
我的意见是,为了保持整洁,使用默认的棱镜方法并将视图模型仅绑定到相应的页面,而不绑定到任何子视图。
任何到页面内组件的绑定都应该通过页面视图模型上的属性进行,这样无论内容视图在显示层次结构中的深度如何,您都可以实现绑定。
例如:
您页面的视图模型
public class PageAViewModel : ViewModelBase
{
public ContentViewAViewModel ContentViewViewModel
{
get { return _contentViewViewModel; }
set { SetProperty(ref _contentViewViewModel, value); }
}
}
您的页面浏览量
<?xml version="1.0" encoding="UTF-8"?>
<views:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:components="clr-YourProject.Components"
xmlns:views="clr-YourProject.Views"
x:Class="YourProject.Views.PageA">
<Grid RowSpacing="0">
<Grid RowSpacing="0">
<components:ContentViewA BindingContext="{Binding ContentViewViewModel}"/>
</Grid>
</Grid>
</views:BasePage>
部分视图确实已过时。它过时的原因是我们将 Region support 引入 Prism 8。在我们为 Prism.Forms 实施区域之前,部分视图总是作为一种快速和临时的解决方案来帮助弥合差距。区域更强大,可以让你做更多的事情,比如嵌套和延迟加载视图。
实际上你拥有的嵌套区域的概念:
ComponentViewA which has its own ViewModel.
Then you have ComponentViewB which has it's own ViewModel and has ComponentViewA as a child
And ComponentViewA is itself a child of AwesomePage
这听起来像是您希望支持的一般概念。所以简短的回答是,在 Prism 7 中没有这样做的好方法。肯定有一些技巧,例如您可以将页面作为参数传递并在后面的代码中设置 属性,例如:
public class ComponentViewB : ContentView
{
public static readonly BindableProperty ParentPageProperty =
BindableProperty.Create(nameof(ParentPage), typeof(Page), typeof(ComponentViewB), null, propertyChanged: OnParentPageChanged);
private static void OnParentPageChanged(BindableObject bindable, object oldValue, object newValue)
{
// This guards the action from being performed more than once.
if(oldValue is null && newValue != null && bindable is ComponentViewB view)
{
// This assumes you've set the property x:Name="componentViewA"
// for your ComponentViewA in XAML
ViewModelLocator.SetAutowirePartialView(view.componentViewA, (view.ParentPage);
}
}
public Page ParentPage
{
get => (Page)GetValue(ParentPageProperty);
set => SetValue(ParentPageProperty, value);
}
}
老实说,如果我今天必须做点什么,我会推荐这样做。一旦我们合并了我在上面引用的 PR,我会建议您更新到预览并迁移到使用区域。
当 ContentView 直接包含在页面中时,我们成功地将 ContentView 连接到它们的 ViewModel,使用 XAML 如:
<local:AwesomeView mvvm:ViewModelLocator.AutowirePartialView=”{x:Reference self}” />
其中 self 是父页面。
但是,我们有包含 ContentView 的 ContentView,并且如上所述对嵌套视图使用 AutoWirePartialView 不起作用。 ContentViews 没有连接到他们的 ViewModels。
查看 Prism 代码:
- AutoWirePartialView 有评论 "This API is Obsolete and will 在 8.0 预览期间被删除
- 属性 更改了 AutoWirePartialView 的处理程序明确检查父级是否为 Page,因此不能与父级 ContentView 一起使用
所以从 Prism 代码中可以很清楚地看出为什么这行不通!
有没有办法用 Prism 实现这一点?
版本: Xamarin.Forms - 4.4.0.991265
棱镜 - 7.1.0.431
我的意见是,为了保持整洁,使用默认的棱镜方法并将视图模型仅绑定到相应的页面,而不绑定到任何子视图。
任何到页面内组件的绑定都应该通过页面视图模型上的属性进行,这样无论内容视图在显示层次结构中的深度如何,您都可以实现绑定。
例如:
您页面的视图模型
public class PageAViewModel : ViewModelBase
{
public ContentViewAViewModel ContentViewViewModel
{
get { return _contentViewViewModel; }
set { SetProperty(ref _contentViewViewModel, value); }
}
}
您的页面浏览量
<?xml version="1.0" encoding="UTF-8"?>
<views:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:components="clr-YourProject.Components"
xmlns:views="clr-YourProject.Views"
x:Class="YourProject.Views.PageA">
<Grid RowSpacing="0">
<Grid RowSpacing="0">
<components:ContentViewA BindingContext="{Binding ContentViewViewModel}"/>
</Grid>
</Grid>
</views:BasePage>
部分视图确实已过时。它过时的原因是我们将 Region support 引入 Prism 8。在我们为 Prism.Forms 实施区域之前,部分视图总是作为一种快速和临时的解决方案来帮助弥合差距。区域更强大,可以让你做更多的事情,比如嵌套和延迟加载视图。
实际上你拥有的嵌套区域的概念:
ComponentViewA which has its own ViewModel.
Then you have ComponentViewB which has it's own ViewModel and has ComponentViewA as a child
And ComponentViewA is itself a child of AwesomePage
这听起来像是您希望支持的一般概念。所以简短的回答是,在 Prism 7 中没有这样做的好方法。肯定有一些技巧,例如您可以将页面作为参数传递并在后面的代码中设置 属性,例如:
public class ComponentViewB : ContentView
{
public static readonly BindableProperty ParentPageProperty =
BindableProperty.Create(nameof(ParentPage), typeof(Page), typeof(ComponentViewB), null, propertyChanged: OnParentPageChanged);
private static void OnParentPageChanged(BindableObject bindable, object oldValue, object newValue)
{
// This guards the action from being performed more than once.
if(oldValue is null && newValue != null && bindable is ComponentViewB view)
{
// This assumes you've set the property x:Name="componentViewA"
// for your ComponentViewA in XAML
ViewModelLocator.SetAutowirePartialView(view.componentViewA, (view.ParentPage);
}
}
public Page ParentPage
{
get => (Page)GetValue(ParentPageProperty);
set => SetValue(ParentPageProperty, value);
}
}
老实说,如果我今天必须做点什么,我会推荐这样做。一旦我们合并了我在上面引用的 PR,我会建议您更新到预览并迁移到使用区域。