2017/3/31

Xamarin.Forms 教學系列文(十二.壹)Styles - 多元件可套用樣式


學習目標
  • Style 的基本屬性與寫法
  • Setter Value 引用資源檔
  • Style 繼承 - BaseOn

可以先複習一下 第十章,有個很重要的東西叫 ResourceDictionary 會在這章節出現。

Xamairn 提供了一個 Style 的類別,顧名思義... 有點類似網頁上的 css。

當同一個畫面上有許多物件要用到相同的屬性時,可以利用 Style 省下許多重複的標籤,讓程式碼簡潔,更好維護。

還記得第十章我們將 Button 的屬性做成資源檔後用 StaticResource 呼叫:
    <Button Text=" Discere faciendo " 
            HorizontalOptions="{StaticResource horzOptions}" 
            VerticalOptions="{StaticResource vertOptions}" 
            BorderWidth="{StaticResource borderWidth}" 
            TextColor="{StaticResource textColor}"
            BackgroundColor="{StaticResource backgroundColor}"
            BorderColor="{StaticResource borderColor}" 
            FontSize="{StaticResource fontSize}" />

其實這樣寫也沒減少多少垃圾標籤...

所以需要 Style 來幫忙!!! 而 Style 也是 ResourceDictionary 的一種,

寫起來會像這樣:
  <ContentPage.Resources>
    <ResourceDictionary>
      <Style x:Key="buttonStyle" TargetType="Button">
        …
      </Style>
    </ResourceDictionary>
  </ContentPage.Resources>


Style 標籤

Style 有三個基本屬性:
  1. x:Key 
  2. TargetType - 要使用此 Style 的物件類別
  3. Setters - 對應到 TargetType 要控制的屬性。

     而 Setter 有兩個屬性可以設定:
  • Property - Visual Element 的屬性名
  • Value - 值

完整的 Style 寫法如下:
 <ContentPage.Resources>
    <ResourceDictionary>
      <Style x:Key="buttonStyle" TargetType="Button">
        <Setter Property="HorizontalOptions" Value="Center" />
        <Setter Property="VerticalOptions" Value="CenterAndExpand" />
        <Setter Property="BorderWidth" Value="3" />
        <Setter Property="TextColor" Value="Red" />
        <Setter Property="FontSize" Value="Large" />
        …
      </Style>
    </ResourceDictionary>
  </ContentPage.Resources>


使用 Style,程式碼更加簡潔:
<StackLayout>
  <Button Text=" Carpe diem " Style="{StaticResource buttonStyle}" />
  <Button Text=" Sapere aude " Style="{StaticResource buttonStyle}" />
  <Button Text=" Discere faciendo " Style="{StaticResource buttonStyle}" />
</StackLayout>

執行結果:



StaticResource in Style

當 Setter 的 Value 有點複雜,或是此 Value 要讓其他 Style 重複利用時,可以使用此技巧。

舉例來說,今天要設定一組 TextColor Setter,其值為 Color.FromHsl 產生的顏色,我們可以先將 Color.FromHsl 寫成一組可用的資源檔,接著在 Setter Value 引用:
<ResourceDictionary>

  <!--做成資源檔-->
  <Color x:Key="btnTextColor" x:FactoryMethod="FromHsla">
    <x:Arguments>
      <x:Double>0.83</x:Double>
      <x:Double>1</x:Double>
      <x:Double>0.75</x:Double>
      <x:Double>1</x:Double>
    </x:Arguments>
  </Color>

  <Style x:Key="buttonStyle" TargetType="Button">
    <!--Value 引用 btnTextColor-->
    <Setter Property="TextColor" Value="{StaticResource btnTextColor}" /> 
  </Style>
</ResourceDictionary>


Style 繼承

Style 是能夠繼承自另一個 Style 的,使用的是 BaseOn 這個屬性。

直接上程式碼:
要注意的是被繼承的 TargetType 必須和繼承的 TargetType 同樣或是上一層 Class 的關係。
    <ContentPage.Resources>
        <ResourceDictionary>

            <Style x:Key="visualStyle" TargetType="VisualElement">
                <Setter Property="BackgroundColor" Value="{toolkit:HslColor H=0, S=1, L=0.8}" />
            </Style>
            
            <!--繼承 visualStyle-->
            <Style x:Key="baseStyle" TargetType="View" BasedOn="{StaticResource visualStyle}">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>

            <!--繼承 baseStyle-->
            <Style x:Key="labelStyle" TargetType="toolkit:AltLabel" BasedOn="{StaticResource baseStyle}">
                <Setter Property="TextColor" Value="Black" />
                <Setter Property="PointSize" Value="12" />
            </Style>

            <!--繼承 baseStyle-->
            <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-->
  <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 必須等 ResourceDictionary 寫好才能用,所以才在中間用 StaticResourceExtension Key="visualStyle" 來設定其 Style。

結果:



在第十章時有講到 ResourceDictionary 在 XAML 內可以為樹狀結構的分布,Visual Element 會引用最接近的 ResourceDictionary,Style 也是依循同樣的規則。

對於大型的專案,有相當多頁面或是 Style 時,為了維護方便,會建議將 Style 寫得越靠近要引用的元件 越好。

下一小節此建議會顯得更加重要! Implicit Style


2 則留言:

  1. 不好意思 請問一下"" 我找不到裡面有"Style"的標籤

    回覆刪除
    回覆
    1. 你指的是 Visual Studio 在 .xaml 檔案內,intellisense 沒下拉可選嗎?

      刪除