sgarcia.dev
sgarcia.dev

Reputation: 6170

XamarinForms XAML: How can I inherit properties from another XAML file like ResourceDictionaries?

I'm using Resource Dictionaries a lot, but it's getting tedious having to copy and paste them from one Xaml to the other to have them all update. The only way I've seen this done is inheriting a style class, but I do not like the way properties are declared in C# (I prefer the more visual tree syntax of XAML). Is there some way to have one XAML inherit from another? or a method like LoadXaml() that I can call on each Xamarin.Forms.ContentPage I create to inherit from a StylePage?

Here is my style xaml page:

<?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="Demo.StylePage">
    <!-- Shared Properties -->
    <ContentPage.Resources>
        <ResourceDictionary>
            <!-- TitleBar Styles -->
            <Style x:Key="TitleBarStyle" TargetType="StackLayout">
                <Setter Property="BackgroundColor" Value="#5db3d6"/>
                <Setter Property="Padding" Value="15,6"/>
                <Setter Property="HeightRequest" Value="44"/>
            </Style>

            <Style x:Key="TitleBarHeaderStyle" TargetType="Label">
                <Setter Property="TextColor" Value="White"/>
                <Setter Property="VerticalOptions" Value="CenterAndExpand"/>
<!--                <Setter Property="FontSize" Value="18"/>-->
                <Setter Property="HorizontalOptions" Value="FillAndExpand"/>
            </Style>

            <Style x:Key="EmptyFrameStyle" TargetType="Frame">
                <Setter Property="HasShadow" Value="false"></Setter>
                <Setter Property="BackgroundColor" Value="Transparent"></Setter>
                <Setter Property="Padding" Value="0,0"></Setter>
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
</ContentPage>

How could I load this resource dictionary from another file? Thank you for your time, Sergei.

Upvotes: 2

Views: 3341

Answers (3)

Sten Petrov
Sten Petrov

Reputation: 11040

You can replace your App.cs with a XAML/cs combo as shown here

The resources defined in your App.xaml will be available for every view loaded in your app.

Make sure your App.xaml file has a build action of "Embedded Resource". Alternatively you can add it as a ContentView with XAML from the UI and then replace ContentView with Application

enter image description here

App.xaml

<Application
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="WorkingWithAppResources.App">
    <Application.Resources>
        <ResourceDictionary>
            <Style x:Key="labelStyle" TargetType="Label">
                <Setter Property="TextColor" Value="Green" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

App.xaml.cs

public partial class App : Application
{
    public App ()
    {
        InitializeComponent ();
        MainPage = YourContentPage(); // change as required
    }
}

Upvotes: 1

ebandersen
ebandersen

Reputation: 2352

ContentPages support inheritance. You can always define one BasePage, implement your resources there, and then have each new ContentPage inherit it. While I've never done this with inheriting xaml, I have used to share analytics, logging, etc. in my BasePage's code-behind (as shown below).

I'd suggest trying a similar approach and just instantiating your resource dictionary in your BasePage.

BaseFormPage:

public class BasePage : ContentPage
    {
        public BasePage () : base () { }

        protected override void OnAppearing ()
        {
            base.OnAppearing ();

            AnalyticsApi.LogPageView ();
            AnalyticsApi.LogEvent(Title + " Page Loaded");

        }
    }

ChildFormPage:

<?xml version="1.0" encoding="UTF-8"?>
<local:BasePage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:MyApp;assembly=MyApp"
             x:Class="MyApp.LoginPage"
             Title="{x:Static local:Strings.SignIn}"
             BackgroundColor="{x:Static local:Colors.ThemeQuaternary}">
    <StackLayout>
        ...
    </StackLayout>
</local:BasePage>

Upvotes: 3

Stephane Delcroix
Stephane Delcroix

Reputation: 16232

In Xamarin.Forms, you can declare resources on every VisualElement. You then access those resources using either {StaticResource} or {DynamicResource}.

The resolution rules applied are roughly as follows:

  • for {StaticResource}:
    • Look in this VisualElement.Resources or any of its parent in the same XAML file
    • Then look in Application.Current.Resources
  • for {DynamicResource}:
    • Look in this VisualElement.Resources or any of its parent, even the ones not defined in the same XAML file, and up to the Application.Resources
    • note that {DynamicResources} supports adding resources later, or changing parents

To answer your question, you can indeed define your Styles in a base class in XAML and use XAML inheritance, or add all your resources to your Application class. If you don't have a XAML file for your Application, just add one, and call InitializeComponents() from the Application constructor.

Upvotes: 0

Related Questions