Xaml Xamarin:通过代码隐藏中的引用设置多个viewmodels

Xaml Xamarin:通过代码隐藏中的引用设置多个viewmodels,xaml,xamarin,xamarin.forms,mvvm,Xaml,Xamarin,Xamarin.forms,Mvvm,我需要根据xaml代码中的代码设置两个ViewModels。或者,如果有更好的方式做,将是伟大的 当我这样做的时候,应用程序崩溃了。当我在代码隐藏(BindingContext=ViewModel)中设置ProductDetailViewModel时,一切正常 更新 将viewModels作为参数传递不是一个好主意。 我现在有一个类“ViewModelLocator”,它包含所有作为静态属性的ViewModels。使用谷歌获取更多信息。这样事情就容易多了 范例 视图模型定位器 public st

我需要根据xaml代码中的代码设置两个ViewModels。或者,如果有更好的方式做,将是伟大的

当我这样做的时候,应用程序崩溃了。当我在代码隐藏(BindingContext=ViewModel)中设置ProductDetailViewModel时,一切正常

更新 将viewModels作为参数传递不是一个好主意。 我现在有一个类“ViewModelLocator”,它包含所有作为静态属性的ViewModels。使用谷歌获取更多信息。这样事情就容易多了

范例 视图模型定位器

public static class ViewModelLocator
{
     public static AddProductViewModel AddProductViewModel { get; set; } = new AddProductViewModel(App.ProductDataStore, App.NavigationService);
}
结束更新

更新2

**Xamarin.Forms.Xaml.XamlParseException:** 'Position 9:10. Can not find the object referenced by `ProductDetailViewModel`'
正如@Waescher所说,最好使用FreshMvvm。静态方法简单快速,但不适合速度较慢的设备或更大的应用程序。谢谢

结束更新2

**Xamarin.Forms.Xaml.XamlParseException:** 'Position 9:10. Can not find the object referenced by `ProductDetailViewModel`'
因为我不能直接在xaml中设置ViewModels,所以我需要从代码隐藏中引用它

请参见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>

如果我正确理解了这一点,并且希望将模式作为构造函数参数传递到视图模型中

    public ProductCustomerPictures(ProductDetailViewModel viewModel)
    {
        InitializeComponent();
        ProductDetailViewModel = viewModel;
        MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
    }
。。。然后你可以完全移除这个

    <ContentPage.BindingContext>
        ...
    </ContentPage.BindingContext>
相反,只需直接在构造函数中设置BindingContext

    public ProductCustomerPictures(ProductDetailViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;    // <-- here
        MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
    }
现在,您可以在绑定表达式中使用名称作为引用:

    <flv:FlowListView FlowColumnCount="3"
        x:Name="listItems"
        FlowItemsSource="{Binding Source={x:Reference thisPage}, Path=MultiMediaPickerViewModel.Media}"
        SeparatorVisibility="None"
        HasUnevenRows="false"
        RowHeight="100"
        HeightRequest="0">

顺便说一下,您可以压缩代码中的属性:

  [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 MultiMediaPickerViewModel MultiMediaPickerViewModel { get; private set; }

    public ProductCustomerPictures(ProductDetailViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
        MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
    }

为什么您认为不能在XAML中设置它?这是什么
ProductDetailViewModel
?它来自哪里?从前面的观点来看。当我这样做时,应用程序崩溃。当我在代码中设置ProductDetailViewModel时,一切正常。只需一次更新。将viewModels作为参数传递不是一个好主意。我现在有一个类“ViewModelLocator”,它将所有ViewModels作为静态属性。我在AppShell.xaml中初始化它们。使用谷歌获取更多信息。如果你想听听我的意见:不要把viewModels作为参数传递,也不要使用静态方法。ViewModels可能会占用大量内存。不要使用“视图到视图”导航,而是使用“视图模型到视图模型”导航。有了这个,你可以很容易地用IoC容器连接起来。帮自己一个忙,检查一下FreshMvvm。
    <flv:FlowListView.BindingContext>
        ...
    </flv:FlowListView.BindingContext>

    public MultiMediaPickerViewModel MultiMediaPickerViewModel { get; private set; }

    public ProductCustomerPictures(ProductDetailViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
        MultiMediaPickerViewModel = new MultiMediaPickerViewModel(MultiMediaPickerServiceStaticVariableHolder.MultiMediaPickerService);
    }