Xamarin.Forms でのスタイルの継承

Download Sampleサンプルのダウンロード

スタイルを他のスタイルから継承することで、重複を減らし、再利用が可能になります。

XAML でのスタイルの継承

スタイルの継承は、Style.BasedOn プロパティを既存の Style プロパティに設定することによって実行されます。 XAML の場合は、BasedOn プロパティを (以前に作成した Style を参照する) StaticResource マークアップ拡張機能に設定することで、これが実現されます。 C# の場合には、BasedOn プロパティを Style インスタンスに設定することによって実現されます。

基本スタイルから継承するスタイルには、新しいプロパティの Setter インスタンスを含めることができます。あるいは、このインスタンスで基本スタイルをオーバーライドできます。 さらに、基本スタイルを継承するスタイルは、同じ型、または基本スタイルの対象となる型から派生した型を対象とする必要があります。 たとえば、基本スタイルが View インスタンスをターゲットしている場合、その基本スタイルに基づくスタイルは View インスタンスをターゲットするか、LabelButton など、View クラスから 派生した型をターゲットにすることができます。

次のコードで、 XAML ページでの明示的なスタイルの継承を示します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.StyleInheritancePage" Title="Inheritance" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
                <Setter Property="HorizontalOptions"
                        Value="Center" />
                <Setter Property="VerticalOptions"
                        Value="CenterAndExpand" />
            </Style>
            <Style x:Key="labelStyle" TargetType="Label"
                   BasedOn="{StaticResource baseStyle}">
                ...
                <Setter Property="TextColor" Value="Teal" />
            </Style>
            <Style x:Key="buttonStyle" TargetType="Button"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="BorderColor" Value="Lime" />
                ...
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <Label Text="These labels"
                   Style="{StaticResource labelStyle}" />
            ...
            <Button Text="So is the button"
                    Style="{StaticResource buttonStyle}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

baseStyleView インスタンスをターゲットし、HorizontalOptions および VerticalOptions プロパティを設定します。 baseStyle は、どのコントロールにも直接設定されません。 代わりに、labelStylebuttonStyle がそれを継承し、追加のバインド可能なプロパティ値を設定します。 その後、labelStyle および buttonStyle は、Style プロパティを設定することで、Label および Button のインスタンスに適用されます。 これで、次のスクリーンショットのような結果になります。

Style inheritance screenshot

Note

暗黙的なスタイルを明示的なスタイルから派生させることはできますが、明示的なスタイルを暗黙的なスタイルから派生させることはできません。

継承チェーンの尊重

スタイルは、ビュー階層内の同じレベル以上のスタイルからのみ継承できます。 これは、次のことを意味します。

  • アプリケーション レベルのリソースは、他のアプリケーション レベルのリソースからのみ継承できます。
  • ページ レベルのリソースは、アプリケーション レベルのリソースや、その他のページ レベルのリソースから継承できます。
  • コントロール レベルのリソースは、アプリケーション レベルのリソース、ページ レベルのリソース、およびその他のコントロール レベルのリソースから継承できます。

この継承チェーンを、次のコード例の中に示します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.StyleInheritancePage" Title="Inheritance" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
              ...
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <StackLayout.Resources>
                <ResourceDictionary>
                    <Style x:Key="labelStyle" TargetType="Label" BasedOn="{StaticResource baseStyle}">
                      ...
                    </Style>
                    <Style x:Key="buttonStyle" TargetType="Button" BasedOn="{StaticResource baseStyle}">
                      ...
                    </Style>
                </ResourceDictionary>
            </StackLayout.Resources>
            ...
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

この例で、labelStyle および buttonStyle はコントロール レベルのリソースですが、baseStyle はページ レベルのリソースです。 ただし、labelStylebuttonStylebaseStyle からの継承を行なう一方で、ビュー階層内のそれぞれの場所が理由で、baseStylelabelStyle もしくは buttonStyle からの継承を行なうことはできません。

C# でのスタイルの継承

C# の場合のページを次のコード例で示します。ここでは、必要なコントロールの Style プロパティに、Style インスタンスが直接割り当てられています。

public class StyleInheritancePageCS : ContentPage
{
    public StyleInheritancePageCS ()
    {
        var baseStyle = new Style (typeof(View)) {
            Setters = {
                new Setter {
                    Property = View.HorizontalOptionsProperty, Value = LayoutOptions.Center    },
                ...
            }
        };

        var labelStyle = new Style (typeof(Label)) {
            BasedOn = baseStyle,
            Setters = {
                ...
                new Setter { Property = Label.TextColorProperty, Value = Color.Teal    }
            }
        };

        var buttonStyle = new Style (typeof(Button)) {
            BasedOn = baseStyle,
            Setters = {
                new Setter { Property = Button.BorderColorProperty, Value =    Color.Lime },
                ...
            }
        };
        ...

        Content = new StackLayout {
            Children = {
                new Label { Text = "These labels", Style = labelStyle },
                ...
                new Button { Text = "So is the button", Style = buttonStyle }
            }
        };
    }
}

baseStyleView インスタンスをターゲットし、HorizontalOptions および VerticalOptions プロパティを設定します。 baseStyle は、どのコントロールにも直接設定されません。 代わりに、labelStylebuttonStyle がそれを継承し、追加のバインド可能なプロパティ値を設定します。 その後、labelStyle および buttonStyle は、Style プロパティを設定することで、Label および Button のインスタンスに適用されます。