如何创建继承自'页面的Xamarin Forms类层次结构?类型?

时间:2017-06-30 08:09:08

标签: c# xamarin xamarin.forms

在Xamarin.Forms中,我试图创建一个我然后子类化的页面,如下所示:

public partial class PageA : ContentPage {
  public PageA() {InitializeComponent ();}
}

public partial class PageB : PageA {
  public PageB() : base() { ... }
}

这两个页​​面都是带有代码隐藏的xaml页面,但是PageB页面不起作用,我不确定为什么(我是XAML,Xamarin,C#和基本编码的新手)。

我现在无法编译代码,因为这一行:

this.FindByName<Label>

警告我:

  

PageB不包含&#39; FindByName&#39;的定义,最好的扩展方法......需要一个类型为&#39;元素&#39;

的接收器

这一行:

await Navigation.PushAsync(new PageB());

给出一个错误,即PageB不是Xamarin.Forms.Page。我不知道为什么PageA会被认为是一种类型,但它确实如此。

问题:

  1. 是否可以创建自定义页面的子类?
  2. 为什么将ContentPage(PageA)子类视为类型&#39;元素&#39;和类型&#39; Page&#39;?为什么PageB不被认为属于那些类型?
  3. 我怀疑我在这里做了很多事情,所以对我如何表达问题以及我应该问什么问题的指示的任何更正都非常受欢迎!

    ===========编辑

    回应以下评论:

    网页A

    .cs文件(codebehind)具有名称空间AppName.FolderName,xaml具有x:Class属性值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>
    

    网页B

    .cs文件(codebehind)具有名称空间AppName.FolderName.SubFolderName,xaml具有x:Class属性值x:Class="AppName.FolderName.SubFolderName.PageB"

    我有以下using 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.SubFolderName.PageB">
    </ContentPage>
    

2 个答案:

答案 0 :(得分:5)

试试这个

  

仅供参考,此代码来自我的应用程序,这是一个工作示例

创建一个基页,如下所示

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

你的基页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();
        }
    }
}

现在派生的页面看起来像这样

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

派生页面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 LoginPage : BasePage
    {
    }
}

答案 1 :(得分:3)

这是Krishna's excellent answer的略微变化 (我本来是评论,但我想清楚地显示代码更改。)

BasePage.xaml 不需要;只需在BasePage.xaml.cs中执行此操作:

using Xamarin.Forms;

public abstract class BasePage : ContentPage
{
    public BasePage()
    {
        // Each sub-class calls InitializeComponent(); not needed here.
    }
}

然后您的子页面必须像在ContentPage构造函数中一样调用InitializeComponent();

我认为这是更好的设计,因为在派生的页面构造函数中看不到InitializeComponent();会令人惊讶;让读者想知道它是否应该在那里但却被意外地遗漏了。这就是我使用这种变化的原因。 每个页面声明看起来就像一个普通的内容页面,除了它继承自BasePage而不是ContentPage。
在常规内容页面和此子类之间来回切换是微不足道的 我通过在ContentPage中使用xamarin表单模板创建其中一个,然后在C#和XAML中将基类更改为BasePage。

因此,派生页面C#变为:

public partial class LoginPage : BasePage
{
    public LoginPage()
    {
        InitializeComponent();
    }
}

和派生页面XAML如Krishna的回答所示。