'How do you create Xamarin Forms class hierarchies inheriting from the 'Page' type?
In Xamarin.Forms, I'm trying to create a page that I then subclass, like this:
public partial class PageA : ContentPage {
public PageA() {InitializeComponent ();}
}
public partial class PageB : PageA {
public PageB() : base() { ... }
}
Both of these pages are xaml pages with code behinds, but the PageB page is not working and I'm not sure why (I'm new to XAML, Xamarin, C# and basically coding in general).
I can't compile the code at the moment, since this line:
this.FindByName<Label>
gives me a warning of:
PageB does not contain a definition for 'FindByName', and the best extension method ... requires a receiver of type 'Element'
And this line:
await Navigation.PushAsync(new PageB());
gives an error that PageB is not an Xamarin.Forms.Page. I don't know why PageA would be considered such a type, but it is.
Questions:
- Is it possible to create subclasses of custom pages?
- Why is a class that subclasses ContentPage (PageA) considered to be both of type 'Element' and of type 'Page'? And why is PageB NOT considered to be of those types?
I suspect I'm wildly off in many things here, so any corrections in how I've phrased the question and pointers to what question I SHOULD be asking are greatly welcome!
=========== EDIT
In response to a comment below:
PageA
The .cs file (codebehind) has the namespace AppName.FolderName
, and the xaml has the x:Class attribute value x:Class="AppName.FolderName.PageA"
<?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="AppName.FolderName.PageA">
... (some elements) ...
</ContentPage>
PageB
The .cs file (codebehind) has the namespace AppName.FolderName.SubFolderName
, and the xaml has the x:Class attribute value x:Class="AppName.FolderName.SubFolderName.PageB"
And I have a reference with the following using AppName.FolderName
, which gives me access to the PageA
class
<?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="AppName.FolderName.SubFolderName.PageB">
</ContentPage>
Solution 1:[1]
Try this
FYI this code is from my app which is a working example
Create a base page as below
<?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="Sthotraani.Views.BasePage">
</ContentPage>
your base page cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Sthotraani.Views
{
public partial class BasePage : ContentPage
{
public BasePage()
{
InitializeComponent();
}
}
}
now derived page looks like this
<?xml version="1.0" encoding="utf-8" ?>
<views:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:Sthotraani.Views;assembly=Sthotraani"
x:Class="Sthotraani.Views.LoginPage"
BackgroundColor="#009688"
xmlns:controls="clr-namespace:Sthotraani.CustomControls;assembly=Sthotraani"
xmlns:converters="clr-namespace:Sthotraani.Converters;assembly=Sthotraani"
xmlns:behaviors="clr-namespace:Sthotraani.Behaviors;assembly=Sthotraani">
</views:BasePage>
derived page cs looks like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Sthotraani.Views
{
public partial class LoginPage : BasePage
{
}
}
Solution 2:[2]
This is a slight variation on Krishna's excellent answer.
(I would have made it a comment, but I wanted to show the code changes clearly.)
IF BasePage does not define any elements in XAML (see Krishna's answer - <views:BasePage>
has no children), THEN BasePage.xaml
is not needed; simply do this in BasePage.xaml.cs
:
using Xamarin.Forms;
public abstract class BasePage : ContentPage
{
public BasePage()
{
// Each sub-class calls InitializeComponent(); not needed here.
}
}
Then your sub-page must call InitializeComponent();
, as you normally do in a ContentPage constructor.
I think this is preferable design, as it would be surprising to NOT see InitializeComponent();
in the derived page constructors; leaves reader wondering if it should be there but was accidentally left out. That is why I use this variation. Each page declaration looks just like a normal content page, except that it inherits from BasePage instead of ContentPage.
Trivial to change back and forth between a regular content page, and this subclass.
I create one of these by using xamarin forms template for ContentPage, then changing base class to BasePage, in both C# and XAML.
So, derived page C# becomes:
public partial class LoginPage : BasePage
{
public LoginPage()
{
InitializeComponent();
}
}
and derived page XAML is as shown in Krishna's answer.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Krishna |
Solution 2 |