You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法使用mvvm:ViewModelLocator创建XAML视图数组的问题排查

问题分析与解决方案

首先来说你遇到的这个XamlParseException错误——找不到Main引用的原因:
XAML的解析是按从上到下的顺序进行的,当解析<x:Array>里的<views:View1>和<views:View2>时,你的ContentPage(也就是x:Name="Main"的那个实例)还没完成初始化,所以此时无法找到名为Main的对象引用,自然就抛出了这个异常。

快速修复当前代码

你可以把AutowirePartialView的引用方式改成相对源绑定,不用依赖x:Name的初始化时机,修改后的代码如下:

<ContentPage x:Class="MainView" 
             xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
             xmlns:views="clr-namespace:Views">
    <CarouselView>
        <CarouselView.ItemsSource>
            <x:Array Type="{x:Type View}">
                <views:View1 mvvm:ViewModelLocator.AutowirePartialView="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}}" />
                <views:View2 mvvm:ViewModelLocator.AutowirePartialView="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}}" />
            </x:Array>
        </CarouselView.ItemsSource>
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <ContentView Content="{Binding .}" />
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
</ContentPage>

这样通过RelativeSource向上查找ContentPage类型的父元素,就能避开初始化顺序的问题,正常完成视图的自动绑定。

用MainViewModel创建视图集合(更符合MVVM模式)

当然可以!而且这种方式更贴合MVVM的设计思想,把视图集合的创建逻辑放到ViewModel里,让页面只负责渲染。具体步骤如下:

1. 在MainViewModel中定义视图集合

using Prism.Mvvm;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using Views;

public class MainViewModel : BindableBase
{
    private ObservableCollection<View> _carouselViews;
    public ObservableCollection<View> CarouselViews
    {
        get => _carouselViews;
        set => SetProperty(ref _carouselViews, value);
    }

    public MainViewModel()
    {
        // 初始化视图集合
        CarouselViews = new ObservableCollection<View>
        {
            new View1(),
            new View2()
        };
    }
}

2. 修改XAML绑定ItemsSource

把原来的<x:Array>替换成绑定到ViewModel的集合,同时注意保持Autowire的配置:

<ContentPage x:Class="MainView" 
             xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
             xmlns:views="clr-namespace:Views"
             mvvm:ViewModelLocator.AutowireViewModel="True">
    <CarouselView ItemsSource="{Binding CarouselViews}">
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <ContentView Content="{Binding .}" 
                             mvvm:ViewModelLocator.AutowirePartialView="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}}" />
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
</ContentPage>

这里把AutowirePartialView移到了ItemTemplate里的ContentView上,这样集合里的每个视图都会自动关联到主页面的ViewModel。

如果想更纯粹的MVVM,还可以在ViewModel中存放子视图的ViewModel集合,然后在ItemTemplate里用DataTemplateSelector根据不同的ViewModel类型渲染对应的视图,这种方式会进一步分离视图和业务逻辑,完全符合MVVM的关注点分离原则。

内容的提问来源于stack exchange,提问作者Esteban Chornet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:29:10