Windows Phone開(kāi)發(fā)(16):樣式和控件模板
在前面資源一文中也提過(guò)樣式,樣式就如同我們做HTML頁(yè)排版時(shí)常用到的CSS樣式表,它是對(duì)于特定婁型的可視化元素,應(yīng)該可以直接說(shuō)是針對(duì)控件的一種可 重用的屬性設(shè)置列表,這樣對(duì)于需要設(shè)置相同屬性值的同類型的多個(gè)控件來(lái)講是大大提高效率,我們不必要為每個(gè)控件做重復(fù)的動(dòng)作。
下面是一個(gè)TextBox的樣式示例,我們希望通過(guò)引用資源中的樣式,使得頁(yè)面上的所有TextBox控件都具有統(tǒng)一的外觀,而且都只能輸入數(shù)字。
- <phone:PhoneApplicationPage.Resources>
- <!--不帶key的樣式,應(yīng)用于所有TextBlock元素-->
- <Style TargetType="TextBlock">
- <Setter Property="FontSize" Value="40"/>
- <Setter Property="Foreground" Value="Yellow"/>
- </Style>
- <!--帶key的樣式,只有引用該資源的元素才應(yīng)用-->
- <Style x:Key="MyTextBoxStyle" TargetType="TextBox">
- <Setter Property="FontSize" Value="40"/>
- <Setter Property="Foreground" Value="Blue"/>
- <Setter Property="InputScope">
- <Setter.Value>
- <InputScope>
- <InputScopeName NameValue="Number"/>
- </InputScope>
- </Setter.Value>
- </Setter>
- </Style>
- </phone:PhoneApplicationPage.Resources>
- <Grid x:Name="LayoutRoot" Background="Transparent">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- </Grid.RowDefinitions>
- <TextBlock Grid.Row="0" x:Name="PageTitle" Text="樣式示例" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
- <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,10,12,0">
- <Grid.RowDefinitions>
- <RowDefinition Height="auto"/>
- <RowDefinition Height="auto"/>
- <RowDefinition Height="auto"/>
- <RowDefinition Height="auto"/>
- <RowDefinition Height="auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="2*"/>
- <ColumnDefinition Width="3*"/>
- </Grid.ColumnDefinitions>
- <TextBlock Grid.Column="0" Grid.Row="0" Text="文本一:"/>
- <TextBlock Grid.Column="0" Grid.Row="1" Text="文本二:"/>
- <TextBlock Grid.Column="0" Grid.Row="2" Text="文本三:"/>
- <TextBlock Grid.Column="0" Grid.Row="3" Text="文本四:"/>
- <TextBlock Grid.Column="0" Grid.Row="4" Text="文本五:"/>
- <TextBox Grid.Column="1" Grid.Row="0" Style="{StaticResource MyTextBoxStyle}" />
- <TextBox Grid.Column="1" Grid.Row="1" Style="{StaticResource MyTextBoxStyle}" />
- <TextBox Grid.Column="1" Grid.Row="2" Style="{StaticResource MyTextBoxStyle}" />
- <TextBox Grid.Column="1" Grid.Row="3"/>
- <TextBox Grid.Column="1" Grid.Row="4"/>
- </Grid>
- </Grid>
1、帶key的樣式,不會(huì)自動(dòng)應(yīng)用到元素/控件上,除非元素的Style屬性引用了該資源的鍵;
2、不帶鍵的樣式資源,將自動(dòng)應(yīng)用于當(dāng)前頁(yè)面(如果資源聲明在當(dāng)前頁(yè))中的所有同類型的元素。
而右面的一列TextBox,由于后面兩個(gè)沒(méi)有顯式設(shè)置Style屬性,故它們保持默認(rèn)樣式。
要自定義控件模板,首先要了解一下?tīng)顟B(tài)。
如果你以前做過(guò)WPF開(kāi)發(fā)你會(huì)知道,在.NET 3.5的時(shí)候,自定義控件模板,針對(duì)控件狀態(tài)的改變所做出的應(yīng)對(duì)策略是通過(guò)觸發(fā)器來(lái)完成的,但到了.NET 4,就有了狀態(tài)的概念,而Silverlight 3也引入這概念,這樣使得控件的狀態(tài)管理更方便也更靈活了。
還有一點(diǎn)就是狀態(tài)有分組的,每個(gè)組里面的狀態(tài)是互斥的,也就是不能同時(shí)發(fā)生,每個(gè)時(shí)刻只允許組內(nèi)一個(gè)狀態(tài)發(fā)生,但不同組之間的狀態(tài)是不沖突的。
- // 摘要:
- // 表示按鈕控件。
- [TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
- [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
- [TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
- [TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
- [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
- [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
- public class Button : ButtonBase
- <phone:PhoneApplicationPage.Resources>
- <ControlTemplate x:Key="Template1" TargetType="ButtonBase">
- <Grid>
- <!--狀態(tài)組-->
- <VisualStateManager.VisualStateGroups>
- <VisualStateGroup x:Name="CommonStates">
- <VisualState x:Name="Normal"/>
- <VisualState x:Name="MouseOver"/>
- <VisualState x:Name="Pressed">
- <Storyboard>
- <DoubleAnimation
- Storyboard.TargetName="pressed"
- Storyboard.TargetProperty="Opacity"
- To="1" Duration="0:0:0.5"/>
- </Storyboard>
- </VisualState>
- <VisualState x:Name="Disabled">
- <Storyboard>
- <DoubleAnimation
- Storyboard.TargetName="disable"
- Storyboard.TargetProperty="Opacity"
- To="0.5" Duration="0:0:0.5"/>
- </Storyboard>
- </VisualState>
- </VisualStateGroup>
- <VisualStateGroup x:Name="FocusStates">
- <VisualState x:Name="Focused">
- <Storyboard>
- <DoubleAnimation
- Storyboard.TargetName="focussbd"
- Storyboard.TargetProperty="Opacity"
- To="0.88"/>
- </Storyboard>
- </VisualState>
- </VisualStateGroup>
- </VisualStateManager.VisualStateGroups>
- <Border BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="{TemplateBinding BorderThickness}">
- <Grid x:Name="background" Background="{TemplateBinding Background}">
- <Rectangle x:Name="pressed" Opacity="0" RadiusX="2" RadiusY="2">
- <Rectangle.Fill>
- <LinearGradientBrush
- StartPoint=".5,0"
- EndPoint=".5,1">
- <GradientStop Color="SkyBlue" Offset=".1"/>
- <GradientStop Color="Blue" Offset=".9"/>
- </LinearGradientBrush>
- </Rectangle.Fill>
- </Rectangle>
- <ContentPresenter x:Name="ContentPresenter"
- HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
- VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
- Margin="{TemplateBinding Padding}"
- Content="{TemplateBinding Content}"
- ContentTemplate="{TemplateBinding ContentTemplate}"/>
- <Rectangle x:Name="disable" Opacity="0" Fill="Gray" RadiusX="2" RadiusY="2"/>
- <Border x:Name="focussbd" BorderBrush="LightGreen" BorderThickness="2" CornerRadius="2" Opacity="0"/>
- </Grid>
- </Border>
- </Grid>
- </ControlTemplate>
- </phone:PhoneApplicationPage.Resources>
- <Grid x:Name="ContentPanel" Margin="12,0,12,0">
- <Button Content="Button" Height="72" HorizontalAlignment="Left" Margin="135,155,0,0" Name="button1" VerticalAlignment="Top" Width="160" Template="{StaticResource Template1}" />
- </Grid>
控件模板有時(shí)候很難一兩句話講清楚,別看它好像很多東西,其實(shí)很簡(jiǎn)單,它無(wú)非包括兩個(gè)東西——狀態(tài)和UI元素,至于怎么個(gè)布局法,完全取決于你希望怎么設(shè)計(jì)了。