Reputation: 1206
Edit: Here's a gist of some of the codebehinds and what it reports out: https://gist.github.com/mattkenefick/5c4effdbad712eb1a42f6cf7207226a6
Note: The question is specific to what's happening in an InitializeComponent call and not to much else. Please read the question in its entirety.
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 the InitializeComponent()
call only happens in MyPage
, then everything works fine (meaning that it doesn't get called in BasePage
)
This question is very specifically about understanding why the BasePage.InitializeComponent()
call breaks the references to XAML elements like x:MyListView
.
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 why the parent InitializeComponent
call causes the NullReferences in the MyPage
class?
Thanks!
Upvotes: 0
Views: 316
Reputation: 9990
First, I assume what you said is true (haven't tried it myself).
If that is the case this happens because your XAML is not inheritable the way C# class is inheritable. So what you do by inhering the XAML page is that you inherit ONLY its C# code, not its XAML contents. Having that in mind, InitializeComponent
shouldn't work.
Upvotes: 0
Reputation: 89179
By default, the variables that Xamarin generates from your XAML are private
, so you can't access them in inherited classes.
Field Modifers allow you change that default behavior
<Label x:Name="publicLabel" x:FieldModifier="public" />
Upvotes: 2