-5

Edit: It's incorrectly marked a duplicate because it's not about identifying the NullReferenceException or even understanding what it is... It's about figuring out why an extended native InitializeComponent() call would make the upper class's XAML elements unable to be referenced. Why does that specific super call cause the NullReference. Hopefully someone capable of seeing the difference will understand. Thank you.


I have a MyPage->BasePage->ContentPage structure. If BasePage executes InitializeComponent() then the XAML elements lose scope within MyPage.. meaning I can't call MyPage.MyListView.ItemSource = xyz without getting a NullReferenceException.

If I disable the InitializeComponent() call from within BasePage, then it works as expected.

What is the BasePage.InitializeComponent() doing that breaks the scope above?

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

On my MyPage.xaml markup, I have various StackLayout elements, ListView, etc. It all exists within a pages:BasePage.Content tag, like so:

<!-- 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>

Within my MyPage.xaml.cs class, the constructor executes the InitializeComponent() method.

Here's what the BasePage.xaml looks like:

<!-- 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>

So to reiterate:

Within the MyPage.xaml.cs, I'm trying to call ListViewView.ItemsSource = SomeDataModel after an async fetch from a REST server.

If the extended BasePage.xaml.cs class calls InitializeComponent() in its constructor... I will get a NullReferenceException when setting the ItemsSource.

If the extended BasePage.xaml.cs class DOES NOT call InitializeComponent() in its constructor... The ItemsSource is correctly set and the list appears.

Can someone explain to me what's happening here so I can successfully initialize everything? If I don't initialize the BasePage, then I can't access elements on it as I'd want to.

Thanks!

Matt Kenefick
  • 1,173
  • 1
  • 13
  • 22
  • can you show the code? :) – Sven-Michael Stübe Aug 25 '19 at 20:21
  • 4
    _"This isn't about understanding what a NullReferenceException is"_ -- then, present your question without mentioning `NullReferenceException`. A question that is truly not asking about the exception would not need to mention it, and _would_ include information explaining what you found when you investigated the NRE, and also _would_ include a good [mcve] reproducing the problem. – Peter Duniho Aug 25 '19 at 20:34
  • It would be awesome if you could provide a [mcve]. – mjwills Aug 26 '19 at 00:08
  • 1
    @PeterDuniho There's a difference between asking what a NullReferenceException is and why it's being thrown. The question is basically, _Why is X null here?_--except we don't know what X is, and we don't know where "here" is. This shouldn't be closed as a duplicate, but Matt, you're going to have to at least provide a stack trace and the code it references, even if it's automatically generated. – Zenexer Aug 26 '19 at 01:01
  • @Zenexer: _"There's a difference between asking what a NullReferenceException is and why it's being thrown"_ -- no, there's not. It's _always_ thrown for the same reason: the code tried to dereference a null reference. Only once someone has gotten _past_ that, and can ask their question without mentioning the NRE _and_ the question is more than "why is this null?", have they investigated enough to push the question to the SO community. And when they do, they need to provide a good, well-written question with a good [mcve], just like everyone else should. – Peter Duniho Aug 26 '19 at 01:03
  • 1
    @PeterDuniho I agree that the question is lacking, but it can be a good question while still mentioning NRE--and I'd rather that Matt keep the mention of NRE, as I'd like to see a stack trace. I also agree that Matt is asking the wrong question here, but it doesn't make sense to mark it as a dupe--he's very clearly not intending to ask what an NRE is. He seems to be running into trouble because he's under the impression that InitializeComponent is guaranteed to avoid throwing an NRE and isn't sure how to proceed with debugging it. – Zenexer Aug 26 '19 at 01:08

1 Answers1

1

Remember, BasePage's constructor is being called prior to MyPage's constructor. This also means that BasePage's InitializeComponent will be called before MyPage's constructor.

The call order is going to effectively look like this, so what's actually happening under-the-hood is slightly different:

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

This creates a dependency issue: nothing in BasePage's InitializeComponent method can depend on anything that's initialized by MyPage. If it does, you'll likely get a NullReferenceException or other unintended behavior.

It's hard to know exactly what the source of your error is without seeing your C# code, but I strongly suspect BasePage.InitializeComponent is referencing something that's not set until MyPage..ctor or MyPage.InitializeComponent runs. You can easily test this by temporarily removing the call to BasePage.InitializeComponent in BasePage..ctor and moving it to the end of MyPage.InitializeComponent.

Zenexer
  • 18,788
  • 9
  • 71
  • 77
  • I understand that order which is why I'm confused. My `BasePage.xaml.cs` doesn't even reference anything in its own XAML for demo purposes; it just calls `InitializeComponent` in the constructor. The `MyPage.xaml.cs` ONLY references an element within the `MyPage.xaml`... it doesn't call anything in BasePage. That's why I'm so confused, because I have them limited to their own scopes but when I let `BasePage` call `InitializeComponent` in its constructor.. then `MyPage` seems to forget what its scope is. – Matt Kenefick Aug 26 '19 at 13:56
  • BasePage.InitializeComponent definitely isn't empty, and that's almost certainly where you're getting the NRE. However, if you don't provide the contents of InitializeComponent and the stack trace, I can't help you any further. – Zenexer Aug 26 '19 at 14:03