就像網頁配合CSS一樣,XAML元素結合Style可以使Silverlight頁面變得絢麗多彩。Silverlight的最大吸引力就是無論你想做什麼格式的,什麼效果的頁面你都可以實現,絕對沒有不可能。想使頁面變得絢麗,簡單Style就可以,想使頁面變得特性十足或是千變萬化,那就學好模板,想要使頁面動起來,Storyboard可以幫助你。
樣式(Style)、模板(Template)很少直接定義在控件或者頁面元素內部,一般都定義在外部資源文件中,這樣不但便於維護,更便於重用。什麼叫資源,凡是放在頁面或控件Resource節點下,或是放在獨立資源文件中的ResourceDictionary節點下的全是資源,Style和Template都屬於資源。
將Style定義在App.xaml文件中,看下面的代碼
- <Application
- x:Class="StyleAndTemplate.App"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
- xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
- <!--Application Resources-->
- <Application.Resources>
- <Style x:Key="MyTextBlock" TargetType="TextBlock">
- <Setter Property="FontSize" Value="50"/>
- <Setter Property="Foreground" Value="Blue"/>
- </Style>
- </Application.Resources>
- <Application.ApplicationLifetimeObjects>
- <!--Required object that handles lifetime events for the application-->
- <shell:PhoneApplicationService
- Launching="Application_Launching" Closing="Application_Closing"
- Activated="Application_Activated" Deactivated="Application_Deactivated"/>
- </Application.ApplicationLifetimeObjects>
- </Application>
將Style定義在單獨的資源文件中,首先需要在項目中添加一個xaml後綴的文件(MyResource.xaml),在文件中寫入如下代碼
- <ResourceDictionary
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
- xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
- <Style x:Key="MyTextBlock" TargetType="TextBlock">
- <Setter Property="FontSize" Value="50"/>
- <Setter Property="Foreground" Value="Blue"/>
- </Style>
- </ResourceDictionary>
- <Application.Resources>
- <ResourceDictionary>
- <ResourceDictionary.MergedDictionaries>
- <ResourceDictionary Source="MyResource.xaml"/>
- </ResourceDictionary.MergedDictionaries>
- </ResourceDictionary>
- </Application.Resources>
上述兩種方式運行效果是一樣的,如下圖所示
樣式(Sytle)
Style主要包含兩種屬性和一個子節點
x:Key屬性是Style的唯一標示,必須有且不能重複,爲控件設置Style時使用,格式Style="{StaticResource Key}"
TargetType屬性,該屬性標示Style應用於何種控件,所有Style只用應用於一種控件,並不是所有的資源都是這樣,比如SolidColorBrush,可以用於任何控件的顏色屬性。這個屬性也是必須有的,加入上面說的第三個命名空間,就可使在文件中使用WP7的基礎弓箭了,這樣輸入TargetType時就會自動提示,如果那個命名空間,就不能使用WP7基礎控件,所以填入內容使也會報錯,這就是他必要的原因,如果使用Toolkit,只要將應用添加項目中,並在資源文件中加以命名空間就行了。
<Setter>子節點,有人說這也是Style的一個屬性,我不反對,但是他的確是只能以子節點的方式使用。
Setter可是設置控件個任何屬性,也就是一個控件可是完全由Style定製。Setter有兩個屬性,Property,用來填入屬性名,Value,用來填入屬性值,也就是說一個Setter設置一個屬性。
上述說的三個屬性時Style的必須屬性,缺一不可,x:Key是所有資源的必須屬性。
不但可以使用Style爲控件定義樣式,一些任何控件都具有的屬性可以放在Resource根節點下,而不必放在Style的Setter中,比如SolidColorBrush可以設置顏色、FontFamily可以設置字體,他們不放在Style中。
樣式是具有優先級的,如果設置使用Style和屬性設置重複後,只有一個起作用,那麼誰起作用呢,一般分三個等級,1、默認樣式,沒有爲控件設置任何樣式,則使用默認樣式,2、Style設置的樣式,設置Style後將覆蓋默認樣式,3、屬性中直接設置,這種方式優先級最高,他優先起作用。
至於Style都可以設置哪些屬性,在TargetType之後,在你寫Setter時,會有自動提示,只有找到自己想要的就行了。
簡單說一下模板(Template)
模板有很多種,我只說兩種萬能模板,其他的,童鞋們自己體會吧,都是一樣的。什麼是萬能模板,就是可以應用到任何可以使用模板的控件上
DataTemplate
這個模板可以說是萬能的,可以用來設置控件的內容(ContentTemplate),也可以設置佈局(ItemTemplate),下面以Button爲例說一下他的用法
在資源中定義一個DataTemplate
- <DataTemplate x:Key="DataKey">
- <StackPanel>
- <TextBlock Text="Templage"/>
- <TextBlock Text="I'm a Template"/>
- </StackPanel>
- </DataTemplate>
<Button Margin="10,120,0,0" VerticalAlignment="Top" Width="259" ContentTemplate="{StaticResource DataKey}">
運行效果如下
看到模板的作用了嗎,這就是我之前說的爲什麼silverlight是變化無窮的,因爲你可以用一個模板將空間做成任何你想要的樣子
ControlTemplate
ControlTemplate一般用Gid開定義控件的佈局,用VisualState控制狀態,一般是動畫,ContentControl用來顯示Content
我們爲了簡單,從Blend複製一個Button的完整Style
- <Style x:Key="MyButtonStyle" TargetType="Button">
- <Setter Property="Background" Value="Transparent"/>
- <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
- <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
- <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
- <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
- <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
- <Setter Property="Padding" Value="10,3,10,5"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="Button">
- <Grid Background="Transparent">
- <VisualStateManager.VisualStateGroups>
- <VisualStateGroup x:Name="CommonStates">
- <VisualState x:Name="Normal"/>
- <VisualState x:Name="MouseOver"/>
- <VisualState x:Name="Pressed">
- <Storyboard>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
- Storyboard.TargetName="ContentContainer">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames
- Storyboard.TargetProperty="BorderBrush"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- </Storyboard>
- </VisualState>
- <VisualState x:Name="Disabled">
- <Storyboard>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
- Storyboard.TargetName="ContentContainer">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames
- Storyboard.TargetProperty="BorderBrush"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
- </ObjectAnimationUsingKeyFrames>
- </Storyboard>
- </VisualState>
- </VisualStateGroup>
- </VisualStateManager.VisualStateGroups>
- <Border x:Name="ButtonBackground"
- BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="{TemplateBinding BorderThickness}"
- Background="{TemplateBinding Background}" CornerRadius="0"
- Margin="{StaticResource PhoneTouchTargetOverhang}">
- <ContentControl x:Name="ContentContainer"
- ContentTemplate="{TemplateBinding ContentTemplate}"
- Content="{TemplateBinding Content}" Foreground="{TemplateBinding
- Foreground}" HorizontalContentAlignment="{TemplateBinding
- HorizontalContentAlignment}" Padding="{TemplateBinding Padding}"
- VerticalContentAlignment="{TemplateBinding
- VerticalContentAlignment}"/>
- </Border>
- </Grid>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
我們看到Style中包含一個ControlTemplate,VisualState設置了點擊時的樣式和禁用時的樣式,加上默認的樣式,默認Button按鈕有三種形態,現在我改變Pressed的狀態動畫,改變背景色爲Red,將這個Style設置給一個Button
- <VisualState x:Name="Pressed">
- <Storyboard>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
- Storyboard.TargetName="ContentContainer">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
- </ObjectAnimationUsingKeyFrames>
- <ObjectAnimationUsingKeyFrames
- Storyboard.TargetProperty="BorderBrush"
- Storyboard.TargetName="ButtonBackground">
- <DiscreteObjectKeyFrame
- KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
- </ObjectAnimationUsingKeyFrames>
- </Storyboard>
- </VisualState>
上面我簡單的改變了一下Pressed狀態的動畫,如果你想得到更加豐富的效果,可以自己定製。
ContentControl是用來顯示內用的控件,所有繼承自ContentControl的控件模板中都有這個屬性,沒有就無法顯示內容了,只剩個空模板了。
在給初學者說一下TemplateBinding,他是用來綁定屬性的,如ContentControl中的Content="{TemplateBinding Content}",意思是ContentControl的Content屬性顯示的是控件的Content屬性的值,也就是Button的值"button"。他跟Binding不一樣,Binding是綁定的數據,如一個對象中的屬性。Person.Name,後面章節馬上介紹Binding,童鞋們別急。
大家如果認爲我寫的內容有用的話就幫頂一下,點一下推薦,你們的支持就是我的動力!!!先謝謝了!!!
想看比較深入的技術的童鞋別急,因爲我這基礎篇已經寫了三分之二了,我儘量在五篇左右將之結束,然後進入開發技巧章節,給他家分享使用的開發技術。
作者 董賀超