Silverlight的每一個控件(Control),都有Template可以完整的改變整個控件的樣式,不像HTML只能設定Style,有更大的彈性,想將Button改成像GridView也是可行的,而ItemsControls列表式控件是ListBox與ComboBox的基類,更多了ItemsPanel、ItemTemplate兩種Template,ListBox與ComboBox中又有ItemContainerStyle,有更多的花樣可以變化。
Silverlight的每一個控件(Control),都有Template可以完整的改變整個控件的樣式,不像HTML只能設定Style,有更大的彈性,想將Button改成像GridView也是可行的,而ItemsControls列表式控件是ListBox與ComboBox的基類,更多了ItemsPanel、ItemTemplate兩種Template,ListBox與ComboBox中又有ItemContainerStyle,有更多的花樣可以變化,本篇主要以它的子類ListBox為例,它們的關係有點像下圖。
ListBox中各種Template的關係圖,一個控件就有四個Template。
ItemsPanel是控件Items的容器,預設的情況下是VirtualizingStackPanel(只會繪需要顯示的子控件,效能較比StackPanel好),如果想要水平的ListBox,可以這樣作。
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
或是可以使用Silverlight Toolkit中的WrapPanel,讓ListBox中的Items有自動換行的效果。
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<controlsToolkit:WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<!--預設的Template,會影響WrapPanel-->
<ControlTemplate>
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
Silverlight Toolkit中WrapPanel的範例,也是將ListBox.ItemsPanel改成設為水平的WrapPanel。
ItemContainerStyle是產生ListBoxItem的樣式,預設為白白的什麼都沒有,可以為他加背景顏色。
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="Azure" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
如果不喜歡MouseOver與Focused的狀態樣式,可以換掉ListBoxItem的Template
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<!--NEW XAML-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
有時ListBoxItem的Content只有文字其他空白,滑鼠點擊ListBoxItem空白處會沒有反應,我會把背景顏色改成透明(請參考Silverlight奇怪的點擊穿透問題)。
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="#00FFFFFF" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
ItemTemplate是產生ListBoxItem中Content的Template,這應該是使用ItemsControls最常用到的設定,會搭配ItemsSource,在用Binding取得Data。
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Photo}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
不過如果只想要單純輸出文字的話,可以使用DisplayMemberPath,就不為了一個TextBlock而撰寫ItemTemplate。