WPF/Silverlight 中的控件都有Style和Template兩種屬性。前者解釋為樣式,是用來改變控件原有屬性的,比如 Button 控件的(Width,Height,Background 等等)。后者被解釋為模版,用於定義控件的內部結構,可以對控件的外觀和形狀進行改變,比如可以把Button控件的形狀由原來的矩形改變圓形。
WPF/Silverlight控件主要分為以下三類:
Control類型
– Template屬性 (ControlTemplate類型)
– ContentPresenter
– ContentTemplate (DataTemplate類型)
ContentControl類型
– Template屬性 (ControlTemplate類型) 繼承自Control
– ContentTemplate (DataTemplate類型)
ItemsControl類型
– Template屬性 (ControlTemplate類型) 繼承自Control
– ItemsPanel屬性 (ItemsPanelTemplate類型) 指定布局容器
– ItemTemplate屬性 (DateTemplate類型) 每個Item的Template
通過上面的Control類型及Template屬性,我們可以發現兩種最基本Template類型,其實就是ControlTemplate和 DateTemplate。
下面通過實例,對他們進行一一介紹和總結。
1、ControlTemplate:用於描述控件本身的視覺樣式和行為,一般用於單一內容控件。
舉例:我們修改一個Button的Template:
<Style x:Key="LxButtonA" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Ellipse Width="80" Height="40" HorizontalAlignment="Center" VerticalAlignment="Center"> <Ellipse.Fill> <RadialGradientBrush> <GradientStop Color="Green" Offset="1"/> <GradientStop Color="White" Offset="0"/> </RadialGradientBrush> </Ellipse.Fill> </Ellipse> <TextBlock FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" Text="Hello"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
對Button應用該樣式:
<Button Style="{StaticResource LxButtonA}" Height="40" Width="80" Content="Silverlight"/>
效果如下圖:
這時候,會發現,我們在Xaml中雖然對Button的Content屬性賦值為“silverlight” ,但是Button並沒有顯示,而是顯示的Template中TextBlock的Text值Hello,這是因為我們定義的ControlTemplate重寫了原來Button中的Content控件,我們可以這樣修改:
<Style x:Key="LxButtonB" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Ellipse Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" HorizontalAlignment="Center" VerticalAlignment="Center"> <Ellipse.Fill> <RadialGradientBrush> <GradientStop Color="Green" Offset="1"/> <GradientStop Color="White" Offset="0"/> </RadialGradientBrush> </Ellipse.Fill> </Ellipse> <!--<TextBlock FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Content}"/>--> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
將原來的模版中的TextBlock控件的Text屬性修改為: Text="{TemplateBinding Content}",TemplateBinding 解釋為模板綁定擴展是用來把原對象中的屬性和模板對象中的屬性聯系起來
為了提高性能,我們可以用一個ControlPresenter來代替TextBlock,效果一樣的。由於篇幅有限,兩者的區別本文不做介紹,具體請點擊這里查看。
對Button應用該樣式:
<Button Style="{StaticResource LxButtonB}" Height="40" Width="80" Content="World"/>
效果如下圖:
再來說說ContentTemplate屬性,這個屬性是ContentControl類的屬性,其返回類型是DataTemplate類,它主要用於在不改變控件行為方式的基礎上,只對控件的內容進行修改。
<Style x:Key="LxButtonC" TargetType="Button"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Image Source="Image/1.png" Height="64" Width="64"/> </DataTemplate> </Setter.Value> </Setter> </Style>
對Button應用該樣式,只是對Button的Content進行了更改,其他行為方式都沒有變化,效果如下圖:
2、DataTemplate:用於描述控件的Content(數據對象)的視覺樣式。
我們來用一個ItemsControl來進行舉例,用ListBox顯示一列圖片,首先我們定義一個類DateItem:
public class DataItem { /// <summary> /// 圖片路徑 /// </summary> public string ImagePath { get; set; } /// <summary> /// 顯示文字 /// </summary> public string ShowText { get; set; } }
定義ListBox的樣式模版並應用該樣式
<Style x:Key="LxListBoxA" TargetType="ListBox"> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel> <Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/> <TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" /> </StackPanel> </DataTemplate> </Setter.Value> </Setter> </Style>
<ListBox x:Name="MyList" Style="{StaticResource LxListBoxA}"/>
對List進行綁定::
List<DataItem> DataList = new List<DataItem>(); DataList.Add(new DataItem() { ImagePath = @"Image/1.png", ShowText = "人物" }); DataList.Add(new DataItem() { ImagePath = @"Image/2.png", ShowText = "樓房" }); DataList.Add(new DataItem() { ImagePath = @"Image/3.png", ShowText = "電池" }); MyList.ItemsSource = DataList;
效果如下圖所示:
對於ItemsControl類型控件,都有ItemsPanel這個屬性,其返回值是ItemsPanelTemplate,用來指定控件的子項的布局樣式,其他控件比如Combox,TreeView,DataGrid,TabelControl也都均有此屬性。
我們可以修改上面ListBox的ItemsPanel屬性,將ListBox豎排變更為橫排顯示:
<Style x:Key="LxListBoxA" TargetType="ListBox"> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel> <Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/> <TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" /> </StackPanel> </DataTemplate> </Setter.Value> </Setter> </Style>
顯示效果如下圖:
其實,在ItemsControl類型的控件中,還有個ItemContainerStyle,這又是什么屬性呢?其實,他是控件子項的樣式,在ListBox里即ListBoxItem的Style屬性,比如我們可以在這個屬性中統一設置ListBoxItem的字體字號:
<Style x:Key="LxListBoxA" TargetType="ListBox"> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel> <Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/> <TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" /> </StackPanel> </DataTemplate> </Setter.Value> </Setter> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="ListBoxItem"> <Setter Property="FontSize" Value="20"/> </Style> </Setter.Value> </Setter> </Style>
運行結果如下圖:
本篇通過實例對WPF/Silverlight 的ControlTemplate和DataTemplate的使用方式進行了總結,另外還有一種HierarchicalDataTemplate繼承與DataTemplate,主要用於對TreeView,Menu等控件的樣式綁定,下一篇我們主要介紹利用HierarchicalDataTemplate層級模版數據類型綁定Silverlight中的TreeView.