微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Xamarin:通过引用后面的代码设置多个视图模型

如何解决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 举报,一经查实,本站将立刻删除。