概述 本文描述幾個WPF的常用特性,包括:樣式、觸發器和控制項模板。 樣式/Style Style就是控制項的外觀,在XAML中,我們通過修改控制項的屬性值來設置它的樣式,如: <!--直接定義style--> <Border Grid.Row="0" Grid.Column="0" Background ...
概述
本文描述幾個WPF的常用特性,包括:樣式、觸發器和控制項模板。
樣式/Style
Style就是控制項的外觀,在XAML中,我們通過修改控制項的屬性值來設置它的樣式,如:
<!--直接定義style-->
<Border Grid.Row="0" Grid.Column="0" Background="Pink"/>
這樣寫的缺點是如果有一組控制項具備同樣的樣式,代碼不能復用,每個都要單獨設置。所以,需要將樣式代碼提取出來,以便共用。
<UserControl.Resources>
<Style x:Key="Border1" TargetType="Border">
<Setter Property="Background" Value="Orange"/>
</Style>
</UserControl.Resources>
<!--在文件頭部定義-->
<Border Grid.Row="0" Grid.Column="1" Style="{StaticResource Border1}"/>
TargetType="Border"表示這個樣式表是針對Border控制項的,Border1是這個樣式的名字,如果不設置Key,表示對該頁面範圍內的所有Border控制項均有效。
上述這個樣式是定義在該控制項頭部的,它的有效範圍就是當前頁面。如果有多個頁面或窗體需要用到同樣的樣式,那就需要在App.xaml中進行定義。
實際應用時,我們一般不會直接在App.xaml中定義樣式,而是會新建一個資源字典文件,在該資源文件中進行定義,然後在App.xaml中包含該文件即可。
資源文件的定義:Style/Colors.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="Border2" TargetType="Border">
<Setter Property="Background" Value="Chocolate"/>
</Style>
</ResourceDictionary>
在App.xaml中包含該資源文件
<Application x:Class="LearnWPF.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Style/Colors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
我們還可以在類庫中定義樣式,定義方式同上,同時,仍需要在在App.xaml中包含該資源文件,但包含方式和本地的不一樣。
<ResourceDictionary Source="pack://application:,,,/LearnWPF.Controls;component/Style/CommonColors.xaml"/>
可以看出,這和我們引用第三方控制項中的樣式資源的方式是一樣的。
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
觸發器/Triggger
在樣式中應用觸發器,是指在控制項某個觸發屬性變化時,要執行的屬性變化,或啟動某個動畫。
<UserControl.Resources>
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
以上表示當IsMouseOver=True時,將修改該控制項的FontSize和FontWeight屬性。IsMouseOver=False時,控制項屬性將恢複原來的值。
控制項模板/ControlTemplate
有時候,我們需要完全修改控制項的外觀,這時就需要用到ControlTemplate,如下代碼定義一個帶指示燈的按鈕
<Window.Resources>
<Style x:Key="myButton" TargetType="Button">
<Setter Property="Background" Value="SeaGreen"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderThickness="1" BorderBrush="Gray" Background="{TemplateBinding Background}" CornerRadius="10" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" >
<Ellipse Width="20" Height="20" Fill="Green" Margin="10"/>
<TextBlock Text="{TemplateBinding Content}" VerticalAlignment="Center" Margin="2 0"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
需要註意:這裡有兩個地方聲明瞭TargetType="Button"。TemplateBinding 表示採用控制項原來的值。在控制項模板的定義中,也是可以使用Trigger的。
<Window.Resources>
<Style x:Key="myButton" TargetType="Button">
<Setter Property="Background" Value="Silver"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderThickness="1" BorderBrush="Gray" Background="{TemplateBinding Background}" CornerRadius="10" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" >
<Ellipse x:Name="ell" Width="20" Height="20" Fill="LightGreen" Margin="10"/>
<TextBlock Text="{TemplateBinding Content}" VerticalAlignment="Center" Margin="2 0"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="ell" Property="Fill" Value="Red"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
與前文提到的Trigger不同,這裡在設置屬性時,多了一個TargetName="ell"
<Setter TargetName="ell" Property="Fill" Value="Red"/>
這表示,該項操作是針對ell這個控制項的。
如果沒有指定TargetName,能設定的屬性僅僅是包含Button這個控制項所具備的屬性,Button是沒有Fill屬性的,就算原始控制項是包含Fill屬性的,也不能保證該屬性的設置能向下延伸到你想要修改的控制項,所以在ControlTemplate中修改控制項屬性時應指定TargetName 。
資源
系列目錄:WPF開發快速入門【0】前言與目錄
代碼下載:Learn WPF: WPF學習筆記 (gitee.com)
簽名區:
如果您覺得這篇博客對您有幫助或啟發,請點擊右側【推薦】支持,謝謝!