如何解决Xamarin:通过引用后面的代码设置多个视图模型
我需要从xaml代码后面的代码中设置两个viewmodel。或者,如果有更好的方法,那就更好了。
当我这样做时,应用程序崩溃。当我在(BindingContext = viewmodel)后面的代码中设置ProductDetailviewmodel时,一切正常。
更新 传递viewmodels作为参数不是一个好主意。 我现在有一个类“ viewmodelLocator”,其中包含所有viewmodels作为静态属性。使用Google获取更多信息。这样一来,事情变得简单了。
示例 viewmodelLocator
public static class viewmodelLocator
{
public static AddProductviewmodel AddProductviewmodel { get; set; } = new AddProductviewmodel(App.ProductDataStore,App.NavigationService);
}
结束更新
更新2
正如@Waescher所说,最好使用FreshMvvm。静态方法既简单又快速,但不适用于速度较慢的设备或大型应用。谢谢。
结束更新2
**Xamarin.Forms.Xaml.XamlParseException:** 'Position 9:10. Can not find the object referenced by `ProductDetailviewmodel`'
由于无法在xaml中直接设置viewmodel,因此需要通过后面的代码进行引用。
请参见xaml代码中的和。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:BoerPlaza.Controls"
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
x:Class="BoerPlaza.Views.Product.ProductCustomerPictures">
<ContentPage.BindingContext>
<x:Reference Name="ProductDetailviewmodel" /><!-- *** First viewmodel ***!-->
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<!-- Total image count -->
<Label Text="{Binding Product.UserImages.Total}"
Style="{StaticResource H2}" />
<!-- Title -->
<Label Text="{Binding Product.Title}"
Style="{StaticResource H1}" />
<!-- reviews -->
<StackLayout Orientation="Horizontal">
<controls:StardisplayTemplateView x:Name="customrattingBar"
SelectedStarValue="{Binding Product.ratingTotal}" />
<Label Text="{Binding Product.ratingAmount,StringFormat='{0} reviews | '}" />
<Label Text="Schrijf een review" />
</StackLayout>
<Label Text="{Binding Product.Title,StringFormat='Heb je een productfoto van {0} die je wilt delen? '}" />
<Button Text="Foto's toevoegen"
Command="{Binding SelectimagesCommand}"
BackgroundColor="{StaticResource neutral-color}"
BorderColor="{StaticResource alt-color}"
BorderWidth="1"
TextColor="{StaticResource primary-color}"
HorizontalOptions="Start"
HeightRequest="40"
FontSize="12" />
<!-- hr -->
<BoxView Style="{StaticResource separator}" />
<flv:FlowListView FlowColumnCount="3"
x:Name="listItems"
FlowItemsSource="{Binding Media}"
SeparatorVisibility="None"
HasUnevenRows="false"
RowHeight="100"
HeightRequest="0">
<flv:FlowListView.BindingContext>
<x:Reference Name="MultiMediaPickerviewmodel" /> <!-- *** Second viewmodel ***!-->
</flv:FlowListView.BindingContext>
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Grid>
<ffimageloading:CachedImage DownsampletoViewSize="true"
HeightRequest="100"
Source="{Binding PreviewPath}"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand">
</ffimageloading:CachedImage>
<Image Source="play"
IsVisible="false"
HorizontalOptions="End"
VerticalOptions="End">
<Image.Triggers>
<DataTrigger targettype="Image"
Binding="{Binding Type}"
Value="Video">
<Setter Property="IsVisible"
Value="True" />
</DataTrigger>
</Image.Triggers>
</Image>
</Grid>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
后面的代码:
[XamlCompilation(XamlCompilationoptions.Compile)]
public partial class ProductCustomerPictures : ContentPage
{
public ProductDetailviewmodel ProductDetailviewmodel
{
get { return _productDetailviewmodel; }
set { _productDetailviewmodel = value; }
}
public MultiMediaPickerviewmodel MultiMediaPickerviewmodel
{
get { return _multiMediaPickerviewmodel; }
set { _multiMediaPickerviewmodel = value; }
}
private ProductDetailviewmodel _productDetailviewmodel;
private MultiMediaPickerviewmodel _multiMediaPickerviewmodel;
public ProductCustomerPictures(ProductDetailviewmodel viewmodel)
{
InitializeComponent();
ProductDetailviewmodel = viewmodel;
MultiMediaPickerviewmodel = new MultiMediaPickerviewmodel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
}
}
解决方法
如果我正确理解了这一点,并且想让模式作为构造函数参数传递给视图模型,那么...
public ProductCustomerPictures(ProductDetailViewModel viewModel)
{
InitializeComponent();
ProductDetailViewModel = viewModel;
MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
}
...那么您可以将其完全删除...
<ContentPage.BindingContext>
...
</ContentPage.BindingContext>
...以及此属性...
public ProductDetailViewModel ProductDetailViewModel
{
get { return _productDetailViewModel; }
set { _productDetailViewModel = value; }
}
相反,只需直接在构造函数中设置BindingContext。
public ProductCustomerPictures(ProductDetailViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel; // <-- here
MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
}
现在,XAML中的每个控件都绑定到ProductDetailViewModel
。
但是您仍然具有应该绑定到MultiMediaPickerViewModel
的FlowListView。代替直接在XAML中设置其绑定上下文,通常将绑定与引用一起使用,但是首先必须给整个页面起一个可在绑定中引用的名称:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
...
...
x:Name="thisPage" <--- here
x:Class="BoerPlaza.Views.Product.ProductCustomerPictures">
现在,您可以在绑定表达式中使用该名称作为引用:
<flv:FlowListView FlowColumnCount="3"
x:Name="listItems"
FlowItemsSource="{Binding Source={x:Reference thisPage},Path=MultiMediaPickerViewModel.Media}"
SeparatorVisibility="None"
HasUnevenRows="false"
RowHeight="100"
HeightRequest="0">
"{Binding Source={x:Reference thisPage},Path=MultiMediaPickerViewModel.Media}"
使用页面本身(按名称thisPage
)并绑定到页面属性Media
的属性MultiMediaPickerViewModel
。
这样,您也可以安全地删除以下代码:
<flv:FlowListView.BindingContext>
...
</flv:FlowListView.BindingContext>
顺便说一下,您可以在后面的代码中压缩属性:
public MultiMediaPickerViewModel MultiMediaPickerViewModel { get; private set; }
public ProductCustomerPictures(ProductDetailViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。