UWP的UI主要由布局容器和內容控件(ContentControl)組成。布局容器是指Grid、StackPanel等繼承自Panel,可以擁有多個子元素的類。與此相對,ContentControl則只能包含單個子元素。
在UWP中,Button、CheckBox、ScrollViewer、Frame、ToolTip等都繼承自ContentControl,其它控件則不是在ContentTemplate中使用ContentControl,就是被ContentControl使用,可以說ContentControl是UWP中最重要的控件。
ContentControl的定義並不復雜,它主要包含這四個屬性:Content,ContentTemplate,ContentTemplateSelector,ContentTransitions。
1. Content
Content支持任何類型,它的值即ContentControl要顯示的對象。可以將Content的類型大致分為兩大類:
- 未繼承自UIElement的類型: ContentControl調用這些類的ToString()方法獲取文本然后顯示。
- 繼承自UIElement的類型: ContentControl直接將它顯示在UI上。
<StackPanel>
<ContentControl>
<AdaptiveTrigger />
</ContentControl>
<ContentControl>
<Rectangle Height="50"
Fill="Red" />
</ContentControl>
</StackPanel>
2. ContentTemplate
要將ContentControl的內容按自己的想法顯示出來,可以使用ContentTemplate屬性public DataTemplate ContentTemplate { get; set; })
。DataTemplate是定義如何顯示綁定的數據對象的XAML標記。DataTemplate定義的XAML塊中元素的DataContext相當於所在ContentControl的Content。
下面的示例演示了怎么將ScoreModel顯示在UI上。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<DataTemplate x:Key="PassTemplate">
<Border Background="Green">
<TextBlock Text="{Binding Score}"
Foreground="White"
FontSize="20"
Margin="20"
HorizontalAlignment="Center" />
</Border>
</DataTemplate>
</Grid.Resources>
<ContentControl ContentTemplate="{StaticResource PassTemplate}">
<local:ScoreModel Score="30" />
</ContentControl>
</Grid>
3. ContentTemplateSelector
如果需要根據Content動態地選擇要使用的ContentTemplate,其中一個方法就是 public DataTemplateSelector ContentTemplateSelector { get; set; }
屬性。
要使用ContentTemplateSelector,首先實現一個繼承DataTemplateSelector的類,並重寫protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
函數,在此函數中返回選中的DataTemplate。
以下的示例演示了SimpleDataTemplateSelector的功能,它通過判斷Score是否大於60,從而選擇返回PassTemplate或者FailTemplate。PassTemplate和FailTemplate都是SimpleDataTemplateSelector 的public屬性,並在XAML中注入到SimpleDataTemplateSelector。
public class SimpleDataTemplateSelector : DataTemplateSelector
{
public DataTemplate PassTemplate { get; set; }
public DataTemplate FailTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var model = item as ScoreModel;
if (model == null)
return null;
if (model.Score >= 60)
return PassTemplate;
else
return FailTemplate;
}
}
<StackPanel>
<StackPanel.Resources>
<DataTemplate x:Key="PassTemplate">
<Border Background="Green">
<TextBlock Text="{Binding Score}"
Foreground="White"
FontSize="20"
Margin="20"
HorizontalAlignment="Center" />
</Border>
</DataTemplate>
<DataTemplate x:Key="FailTemplate">
<Border Background="Red">
<TextBlock Text="{Binding Score}"
Foreground="White"
FontSize="20"
Margin="20"
HorizontalAlignment="Center" />
</Border>
</DataTemplate>
<local:SimpleDataTemplateSelector PassTemplate="{StaticResource PassTemplate}"
FailTemplate="{StaticResource FailTemplate}"
x:Key="DataTemplateSelector" />
<Style TargetType="ContentControl">
<Setter Property="ContentTemplateSelector"
Value="{StaticResource DataTemplateSelector}" />
</Style>
</StackPanel.Resources>
<ContentControl>
<local:ScoreModel Score="60" />
</ContentControl>
<ContentControl>
<local:ScoreModel Score="30" />
</ContentControl>
</StackPanel>
注意:ContentTemplateSelector的缺點是需要創建多個模板,通常同一組數據的模板只有少部分的差別,可以在同一個模板中通過IValueConverter等方式顯示不同的格式。
4. ContentTransitions
public TransitionCollection ContentTransitions { get; set; }
是類型為Transition的集合,提供Content改變時的過渡動畫。
<ContentControl x:Name="ContentControl">
<ContentControl.ContentTransitions>
<TransitionCollection>
<AddDeleteThemeTransition />
</TransitionCollection>
</ContentControl.ContentTransitions>
</ContentControl>
UWP提供了很多優秀的動畫效果,適當使用可以給人很好的用戶體驗。如果沒有優秀的UI設計,老老實實用默認的ContentTransitions就不會錯。