我确切的问题是我试图在我的Xamarin应用程序中为全局的所有页面添加逻辑。
也就是说,我正在尝试创建一个所有页面都继承自的“母版页”。我将页眉/页脚和导航逻辑放在这个“母版页”中,这样我就不必在每个页面上重写它。 ...我说“母版页”,因为Xamarin有一个叫做master-detail的页面,这不是我所说的。我在谈论您可能在ASP.NET Web窗体中使用的母版页的概念。与Xamarin最接近的类比是<ControlTemplate>
,它只需要您的工作,就可以提供与您实际可能认为的母版页相同的效果。它看起来像这样:
App.xaml(母版页的正文)
...
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MainPageTemplate">
<StackLayout>
<Label Text="{TemplateBinding HeaderText}" />
<ContentPresenter /> <!-- this is a placeholder for content -->
<Label Text="{TemplateBinding FooterText}" />
</StackLayout>
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
...
MyPage.xaml(主页面中的内容)
<!-- Translation: this page inherits from CoolApp.Views.MyMasterPage.cs -->
<Views:MyMasterPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Views="clr-namespace:CoolApp.Views"
x:Class="CoolApp.Views.MyPage"
ControlTemplate="{StaticResource MainPageTemplate}">
<Label Text="I am the content" />
</Views:MyMasterPage>
MyMasterPage.cs(共享页眉/页脚和导航逻辑)
// it inherits from ContentPage here, which works fine. so long as your app only uses ContentPages
public class MyMasterPage : ContentPage, INotifyPropertyChanged
{
...
public static BindableProperty HeaderTextProperty;
public string HeaderText
{
get { return (string)GetValue(HeaderTextProperty); }
set
{
HeaderTextProperty = BindableProperty.Create("HeaderText", typeof(string), typeof(SearchPage), value);
OnPropertyChanged("HeaderText");
}
}
// footer logic
// navigation logic
...
}
这个母版页设置非常适合我,直到我需要使用ContentPage
以外的页面类型。具体来说,我需要一个CarouselPage
以完全相同的方式工作。在上面的代码中,我可以让MyMasterPage.cs
继承CarouselPage
而不是ContentPage
,这样就可以了,除非我在两个不同的母版页中拥有全局页眉/页脚和导航逻辑。我不能把逻辑放在继承自Page
的母版页中,因为那时我的页面将是Page
而不是ContentPage
和CarouselPage
。但如果我能直接修改Page
那么ContentPage
和CarouselPage
都会得到我的改变。也许这有点像这样?
我希望它很清楚但是如果不是我想问的问题是如何将我的页眉和页脚以及导航逻辑全部放到一个母版页中?
我有与nbpeth扩展相同的推理
如果你想为你的所有页面添加一个属性(这里是MyContentPage
和MyCarouselPage
),你可能想为每个页面创建一个主页面而不是只有一个主页面,但是将导航逻辑集中在扩展类中
你可以尝试类似下面的东西(我不保证这段代码有效,我手边没有Xamarin设置)
public static class PageExtensions
{
public string GetMyValue(this Page page, BindableProperty headerTextProperty)
{
return (string)page.GetValue(headerTextProperty);
}
public void SetMyValue(this Page page, out BindableProperty headerTextProperty, string value)
{
headerTextProperty = null;
if (page is INotifyPropertyChanged notifyPage)
{
headerTextProperty = BindableProperty.Create("HeaderText", typeof(string), typeof(SearchPage), value);
notifyPage.OnPropertyChanged("HeaderText");
}
}
}
public class MyMasterContentPage : ContentPage
{
// ...
public BindableProperty HeaderTextProperty;
public string HeaderText
{
get { return GetMyValue(HeaderTextProperty); }
set { SetMyValue(out HeaderTextProperty, value); }
}
}
public class MyContentPage : MyMasterContentPage, INotifyPropertyChanged
{
}
public class MyMasterCarouselPage : CarouselPage
{
// ...
public BindableProperty HeaderTextProperty;
public string HeaderText
{
get { return GetMyValue(HeaderTextProperty); }
set { SetMyValue(out HeaderTextProperty, value); }
}
}
public class MyCarouselPage : MyMasterCarouselPage, INotifyPropertyChanged
{
}
你仍然会有一些重复的代码,但不是重复的逻辑
我听说为超类添加功能并思考扩展。我对c#一无所知,但是,例如,在swift中你可以向现有类型添加行为。但是,这不是通过修改孩子来实现的,但是你可以给予超类新的能力。不确定这是否正是您在用例https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods中寻找的内容