-5

编辑:它被错误地标记为重复,因为它不是关于识别NullReferenceException甚至理解它是什么......它是关于弄清楚为什么扩展的本机InitializeComponent()调用会使上层类的 XAML 元素无法被引用。为什么那个特定的超级调用会导致 NullReference。希望有能力看到差异的人会理解。谢谢你。


我有一个MyPage->BasePage->ContentPage结构。如果BasePage执行InitializeComponent(),则 XAML 元素在 .. 内失去范围,MyPage这意味着我无法MyPage.MyListView.ItemSource = xyz在没有得到 NullReferenceException 的情况下调用。

如果我从内部禁用InitializeComponent()呼叫BasePage,那么它会按预期工作。

BasePage.InitializeComponent()打破上述范围的行为是什么?

   Models
   Pages
     ├ BasePage.xaml
     |   ⤷ BasePage.xaml.cs
     └ MyPage.xaml
         ⤷ MyPage.xaml.cs
   Views
   App.xaml
     ⤷ App.xaml.cs

在我的MyPage.xaml标记上,我有各种 StackLayout 元素、ListView 等。它们都存在于一个pages:BasePage.Content标签中,如下所示:

<!-- for s/o: MyPage.xaml -->
<?xml version="1.0" encoding="utf-8" ?>
<pages:BasePage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:pages="clr-namespace:Namespace.Pages"
    xmlns:views="clr-namespace:Namespace.Views"
    x:Class="Namespace.Pages.MyPage">

    <pages:BasePage.Content>

        <ListView x:Name="ListViewView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Image Source="{Binding imageUrl}" />
                            <Label Text="{Binding formattedDayOfWeek}" />
                            <Label Text="{Binding formattedDate}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

    </pages:BasePage.Content>

</pages:BasePage>

在我的MyPage.xaml.cs类中,构造函数执行该InitializeComponent()方法。

外观如下BasePage.xaml

<!-- for s/o: BasePage.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"
    x:Class="Namespace.Pages.BasePage"
    x:Name="_parent">

    <ContentPage.Content>
        <StackLayout x:Name="VerticalLayout" BackgroundColor="#f1f1f1">
            <ContentView
                x:Name="cv"
                x:FieldModifier="public"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="FillAndExpand"
                Content="{Binding Path=ViewContent, Source={x:Reference _parent}}" />
        </StackLayout>
    </ContentPage.Content>

</ContentPage>

所以重申:

在 中MyPage.xaml.cs,我试图ListViewView.ItemsSource = SomeDataModel在从 REST 服务器异步获取之后调用。

如果扩展BasePage.xaml.cs类在其构造函数中调用InitializeComponent()...我将在设置 ItemsSource 时收到 NullReferenceException。

如果扩展BasePage.xaml.cs类没有InitializeComponent()在其构造函数中调用... ItemsSource 已正确设置并出现列表。

有人可以向我解释这里发生了什么,以便我可以成功初始化所有内容吗?如果我不初始化 BasePage,那么我将无法按我的意愿访问其上的元素。

谢谢!

4

1 回答 1

1

请记住,BasePage 的构造函数在 MyPage 的构造函数之前被调用。这也意味着 BasePage 的 InitializeComponent 将在 MyPage 的构造函数之前被调用。

调用顺序实际上看起来像这样,所以实际上在幕后发生的事情略有不同:

  1. BasePage..ctor
  2. BasePage.InitializeComponent
  3. MyPage..ctor
  4. MyPage.InitializeComponent

这会产生一个依赖问题:BasePage 的 InitializeComponent 方法中的任何内容都不能依赖于由 MyPage 初始化的任何内容。如果是这样,您可能会得到一个NullReferenceException或其他意外行为。

如果不查看 C# 代码,很难确切知道错误的根源是什么,但我强烈怀疑BasePage.InitializeComponent它引用了一些未设置MyPage..ctorMyPage.InitializeComponent运行的东西。您可以通过暂时删除对BasePage.InitializeComponentin的调用BasePage..ctor并将其移至MyPage.InitializeComponent.

于 2019-08-26T01:20:26.650 回答