樣式繼承
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子項:

但是假設你現在想要擴充這種風格,但對于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的元素形式是一個很好的解決方案。 頁面的整個背景基于此樣式着色,并且樣式也由所有其他樣式繼承:
如果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從其他樣式派生樣式,并且可以在可視樹中的不同級别定義樣式,這些樣式派生自可視樹中較高的樣式或替換它們完全。
對于具有多個頁面和大量标記的大型應用程式,定義樣式的建議非常簡單 - 将樣式定義為盡可能接近使用這些樣式的元素。
遵循此建議有助于維護程式,并在使用隐式樣式時變得特别重要。