天天看點

第12章 樣式(三)樣式繼承

樣式繼承

Style的TargetType提供兩種不同的功能:下一節隐式樣式中描述了其中一種功能。 另一個函數是為了XAML解析器的好處。 XAML解析器必須能夠解析Setter對象中的屬性名稱,并且為此需要TargetType提供的類名。

樣式中的所有屬性必須由Target?Type屬性中指定的類定義或繼承。 設定Style的可視元素的類型必須與TargetType或TargetType的派生類相同。

如果隻需要為View定義的屬性設定樣式,則可以将TargetType設定為View,并仍然使用按鈕上的樣式或任何其他View派生,如在BasicStyle程式的此修改版本中:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BasicStyle.BasicStylePage">
 
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="viewStyle" TargetType="View">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
                 <Setter Property="BackgroundColor" Value="Pink" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <Button Text=" Carpe diem "
                Style="{StaticResource viewStyle}" />
        <Label Text ="A bit of text"
               Style="{StaticResource viewStyle}" />
 
        <Button Text=" Sapere aude "
                Style="{StaticResource viewStyle}" />
        <Label Text ="Another bit of text"
               Style="{StaticResource viewStyle}" />
        <Button Text=" Discere faciendo "
                Style="{StaticResource viewStyle}" />
    </StackLayout>
</ContentPage>           

如您所見,相同的樣式應用于StackLayout的所有Button和Label子項:

第12章 樣式(三)樣式繼承

但是假設你現在想要擴充這種風格,但對于Button和Label則不同。那可能嗎?

是的。樣式可以源自其他樣式。 Style類包含一個名為BasedOn的屬性Style。在代碼中,您可以将此BasedOn屬性直接設定為另一個Style對象。在XAML中,将BasedOn屬性設定為引用先前建立的樣式的StaticResource标記擴充。新樣式可以包含新屬性的Setter對象,或者使用它們覆寫早期樣式中的屬性。 BasedOn樣式必須以新樣式TargetType的相同類或祖先類為目标。

這是名為StyleInheritance的項目的XAML檔案。該應用程式有兩個目的引用Xamarin.FormsBook.Toolkit程式集:它使用HslColor标記擴充來證明标記擴充是Setter對象中的合法值設定,并且可以證明可以為自定義類定義樣式,在這種情況下AltLabel。

ResourceDictionary包含四種樣式:第一種具有“visualStyle”的字典鍵。帶有“baseStyle”字典鍵的Style來自“visualStyle”。帶有“la?belStyle”和“buttonStyle”鍵的樣式來自“baseStyle”:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit=
                 "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
             x:Class="StyleInheritance.StyleInheritancePage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="visualStyle" TargetType="VisualElement">
                <Setter Property="BackgroundColor"
                        Value="{toolkit:HslColor H=0, S=1, L=0.8}" />
            </Style>
            <Style x:Key="baseStyle" TargetType="View"
                   BasedOn="{StaticResource visualStyle}">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>
            <Style x:Key="labelStyle" TargetType="toolkit:AltLabel"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="TextColor" Value="Black" />
                <Setter Property="PointSize" Value="12" />
            </Style>
            <Style x:Key="buttonStyle" TargetType="Button"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="TextColor" Value="Blue" />
                <Setter Property="FontSize" Value="Large" />
                <Setter Property="BorderColor" Value="Blue" />
                <Setter Property="BorderWidth" Value="2" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Style>
        <StaticResourceExtension Key="visualStyle" />
    </ContentPage.Style>
    <StackLayout>
        <Button Text=" Carpe diem "
                Style="{StaticResource buttonStyle}" />
        <toolkit:AltLabel Text ="A bit of text"
                          Style="{StaticResource labelStyle}" />
        <Button Text=" Sapere aude "
                Style="{StaticResource buttonStyle}" />
        <toolkit:AltLabel Text ="Another bit of text"
                          Style="{StaticResource labelStyle}" />
        <Button Text=" Discere faciendo "
                Style="{StaticResource buttonStyle}" />
    </StackLayout>
</ContentPage>           

在參考資源部分之後,立即将頁面本身的Style屬性設定為“visualStyle”樣式:

<ContentPage.Style>
    <StaticResourceExtension Key="visualStyle" />
</ContentPage.Style>           

因為Page派生自VisualElement而不是View,是以這是可以應用于頁面的資源詞典中的唯一樣式。 但是,在Re?sources部分之後才能将樣式應用于頁面,是以使用StaticResource的元素形式是一個很好的解決方案。 頁面的整個背景基于此樣式着色,并且樣式也由所有其他樣式繼承:

第12章 樣式(三)樣式繼承

如果AltLabel的樣式僅包含Label定義的屬性的Setter對象,則TargetType可以是Label而不是AltLabel。但Style具有PointSize屬性的Setter。該屬性由AltLabel定義,是以TargetType必須是toolkit:AltLabel。

可以為PointSize屬性定義Setter,因為PointSize由可綁定屬性支援。如果将AltLabel中BindableProperty對象的可通路性從公共更改為私有,則該屬性仍可用于AltLabel的許多正常用法,但現在PointSize可以不在樣式Setter中設定。 XAML解析器會抱怨它無法找到PointSizeProperty,它是支援PointSize屬性的可綁定屬性。

您在第10章中發現了StaticResource的工作原理:當XAML解析器遇到StaticResource标記擴充時,它會在可視化樹中搜尋比對的字典鍵。這個過程對風格有影響。您可以在一個“資源”部分中定義樣式,然後使用可視樹中較低的“資源”部分中具有相同字典鍵的另一個樣式覆寫該樣式。将BasedOn屬性設定為StaticResource标記擴充時,必須在相同的Resources部分(如StyleInheritance程式中示範)或可視樹中較高的Resources部分中定義您派生的樣式。

這意味着您可以使用兩種分層方式在XAML中建構樣式:您可以使用BasedOn從其他樣式派生樣式,并且可以在可視樹中的不同級别定義樣式,這些樣式派生自可視樹中較高的樣式或替換它們完全。

對于具有多個頁面和大量标記的大型應用程式,定義樣式的建議非常簡單 - 将樣式定義為盡可能接近使用這些樣式的元素。

遵循此建議有助于維護程式,并在使用隐式樣式時變得特别重要。

繼續閱讀