原文: 控件模闆
1、了解邏輯樹與可視化樹。
添加的元素分類稱之為邏輯樹,可視化樹是邏輯樹的擴充版本,目的用于将元素分成更小的部分。WPF提供了用于浏覽邏輯樹和可視化樹的兩個類:System.Windows.LogicalTreeHelper和System.Windows.Media.VisualTreeHelper。VisualTreeHelper類還提供了一種研究應用程式中可視化樹的有趣的方法,使用GetChild()方法,可以周遊任意序列槽的可視化樹。
2、可視化樹有兩項非常重要的工作。
2.1)、可使用樣式改變可視化樹的元素。可使用Style.TargetType(很重要,假設不指定類型為Button,那麼Button元素應用此模闆不會顯示内容)屬性指定修改的特定元素,甚至當控件屬性發生變化時,可使用觸 發器自動完成更新。
2.2)、可為控件建立新模闆。
3、分析可視化樹。
先分析一下MainWinow視窗中的元素的邏輯樹。
<Window x:Class="可視化樹.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Margin="5">
<Button Name="btn1" Padding="5" Margin="5" Click="cmd_Click">First Button</Button>
<Button Name="btn2" Padding="5" Margin="5" Click="cmd_Click">Second Button</Button>
</StackPanel>
</Window>
邏輯樹:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuUzNzEzMhFWNwEGOlZTO5gjNiVDNmdjN3QmY1gTYjZGMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
可視化樹:
建立一個名叫VisualTreeDisplay的Windows視窗,在視窗背景寫代碼。
VisualTreeDisplay視窗的xaml代碼:
<Window x:Class="可視化樹.VisualTreeDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="VisualTreeDisplay" Height="300" Width="300">
<TreeView Name="treeElements"></TreeView>
</Window>
VisualTreeDisplay視窗的背景代碼:
public partial class VisualTreeDisplay : Window
{
public VisualTreeDisplay()
{
InitializeComponent();
}
public void ShowVisualTree(DependencyObject element)
{
//先清除集合中的項。
treeElements.Items.Clear();
ProcessElement(element, null);
}
private void ProcessElement(DependencyObject element, TreeViewItem previousItem)
{
//建立視圖樹。
TreeViewItem item = new TreeViewItem();
//擷取依賴元素标題。
item.Header = element.GetType().Name;
//打開折疊。
item.IsExpanded = true;
if (previousItem == null)
{
treeElements.Items.Add(item);
}
else
{
previousItem.Items.Add(item);
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
ProcessElement(VisualTreeHelper.GetChild(element, i), item);
}
}
}
在MainWindow中xaml代碼:
<Window x:Class="可視化樹.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Margin="5">
<Button Padding="5" Margin="5" Click="cmd_Click">First Button</Button>
<Button Padding="5" Margin="5" Click="cmd_Click">Second Button</Button>
</StackPanel>
</Window>
MainWindow背景代碼:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void cmd_Click(object sender, RoutedEventArgs e)
{
//檢視視窗的可視化狀态:
//VisualTreeDisplay vtd = new VisualTreeDisplay();
//vtd.ShowVisualTree((this));
//vtd.Show();
//檢視Button的可視化狀态。
VisualTreeDisplay vtd = new VisualTreeDisplay();
vtd.ShowVisualTree((FrameworkElement)sender);
vtd.Show();
}
}
檢視視窗的可視化狀态(參數傳的this),會顯示出可視化邏輯狀态視窗:
檢視button的可視化邏輯視窗(裡面有Border元素(用于修飾)和ContentPresenter元素(顯示内容)):
在<StackPanel> 元素中再添加一個Image元素,命名為img1,接下來看看圖檔的可視化狀态,說明(就顯示個Image,說明沒有可視化邏輯顯示,不能應用模闆):
private void img1_MouseDown(object sender, MouseButtonEventArgs e)
{
VisualTreeDisplay vtd = new VisualTreeDisplay();
vtd.ShowVisualTree((FrameworkElement)sender);
vtd.Show();
}
在上面的Window視窗中,可視化樹包含了一個Border元素,這個Border元素又包含了一個AdornerSecorator元素(用于修飾),AdornerDecorator元素内是一個ContentPresenter元素(該元素承載了視窗内容),視窗内包含了一的StackPanel面闆具有兩個Button控件,每個Button控件包含了一個ButtonChrome元素(該元素繪制按鈕的标準可視化外觀)和一個ContentPresenter元素(該元素包含了元素的内容),每個按鈕額ContentPresenter元素是一個TextBlock元素,TextBlock元素封裝了在視窗中可見的文本。
4、了解模闆
模闆主要用于修改元素外觀,但不能修改其行為。模闆一般分為三種模闆,分别是:控件模闆(ControlTemplate)、資料模闆(DataTemplate)和面闆模闆(ItemPanelTemplate),這些模闆都繼承自FrameworkTemplate基類。控件模闆提供了在可視化樹種看到的擴充内容,ButtonChorme類定義按鈕的标準可視化外觀,而ContentPresenter類存儲了提供的所有内容。其中,ButtonChorme類繼承自Decorator類(與Border類非常類似),這意味着這些類是為了在其他元素周圍添加圖形裝飾而設計的。
5、建立簡單控件模闆。
為Button設定模闆。
xaml代碼:
<Window.Resources>
<!--在資源中定義一個名叫button_template的模闆-->
<ControlTemplate x:Key="button_template" TargetType="{x:Type Button}>
<!--添加Border元素,為其設定屬性-->
<Border BorderBrush="Orange" Background="LightCyan" TextBlock.Foreground="Black" BorderThickness="2" CornerRadius="5">
<ContentPresenter RecognizesAccessKey='True' HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Border>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<!--為第一個Button元素設定模闆。-->
<Button Template="{StaticResource button_template}" Padding="5" Margin="5" Height="50">我是Button1</Button>
<Button Padding="5" Margin="5" Height="50">我是Button2</Button>
</StackPanel>
效果圖:
在上面的控件模闆中,設定了TargetType屬性,以明确訓示該模闆是為按鈕設計的,與樣式類似,這總是一個可以遵循的好約定,在内容控件(如Button)中也需要使用該約定。否則ContentPresenter元素就不能工作。從技術角度看,ContentPresenter之是以能工作,是因為它有一個模闆綁定,用于将ContentPresenter.Content屬性設定為Button.Content屬性,然而該綁定是隐式的。
6、模闆綁定。
<StackPanel>
<!--為第一個Button元素設定模闆。-->
<Button Template="{StaticResource button_template}" Padding="5" Margin="10">我是Button1</Button>
<Button Padding="5" Margin="5" Height="50">我是Button2</Button>
</StackPanel>
在該例中存在一個問題,現在為按鈕添加的Margin屬性指定為10,并将padding屬性的值設定為5,Stackpanel控件關注的是按鈕的Margin屬性,卻忽略了Padding屬性,使按鈕的内容和側邊擠壓在一起,此處額問題是Padding屬性不起作用,除非在模闆中特别注意它,幸運的是WPF專門針對該目的設計了一個工具,模闆綁定。通過使用模闆綁定,模闆可從應用模闆的控件中提取一個值,就是為ContentPresenter元素中的Margin屬性通過模闆綁定到Paddding屬性中。
<!--通過模闆綁定到Padding屬性上-->
<ContentPresenter Margin="{TemplateBinding Padding}" RecognizesAccessKey='True' HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
<StackPanel>
<!--為Button元素設定模闆。這樣Padding屬性就其作用了(如果為button設定了Height屬性,将看不到效果,切記!)-->
<Button Template="{StaticResource button_template}" Padding="20" Margin="10" >我是Button1</Button>
</StackPanel>
7、改變屬性的觸發器。
根據之前的為Button設定簡單模闆綁定,雖然可以改變元素的外觀,但把滑鼠放到元素上,或者點選圖檔時沒有什麼反應,這個時候使用屬性觸發器的IsMouseOver和IsPressed屬性來解決這個問題。其中,IsMouseOver是滑鼠滑到元素上的效果,IsPressed是點選圖檔的效果。設定效果的時候,可通過TargetName指定要修改的具體元素的屬性。
<Window.Resources>
<!--在資源中定義一個名叫button_template的模闆-->
<ControlTemplate x:Key="button_template" TargetType="{x:Type Button}">
<!--添加Border元素,為其設定屬性-->
<Border Name="Border" BorderBrush="Orange" Background="LightCyan" TextBlock.Foreground="Black" BorderThickness="2" CornerRadius="5">
<ContentPresenter Margin="{TemplateBinding Padding}" RecognizesAccessKey='True' HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Border>
<!--設定屬性觸發器-->
<ControlTemplate.Triggers>
<!--設定一個滑鼠移動到元素上的效果(用IsMouseOver屬性)-->
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="DarkRed"></Setter>
<Setter TargetName="Border" Property="BorderBrush" Value="Red"></Setter>
</Trigger>
<!--設定一個點選元素的效果(用IsPressed屬性)-->
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="Yellow"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<!--為第一個Button元素設定模闆。-->
<Button Template="{StaticResource button_template}" Padding="20" Margin="10" >我是Button1</Button>
<Button Padding="5" Margin="5" Height="50">我是Button2</Button>
</StackPanel>
8、焦點訓示器。
在以上案例中,如果存在多個按鈕,如果點選了其中的一個按鈕,不能明确地看出此按鈕是否擷取了焦點,但是可以很容易地添加另一個元素以顯示是否具有焦點,并且可以簡單地使用觸發器根據Button.IsKeyBoardFocused屬性隐藏顯示該屬性。
實作思路是:在Border元素中添加一個Grid元素,在Grid元素中添加一個Rectangle元素(預設是隐藏),然後再添加一個Contentpresenter元素。當點選圖檔的時候,觸發Button元素的IsKeyboardFocused屬性,然後将Rectangle顯示出來。
<Window.Resources>
<!--在資源中定義一個名叫button_template的模闆-->
<ControlTemplate x:Key="button_template" TargetType="{x:Type Button}">
<Border Name="Border" BorderBrush="Orange" Background="LightCyan" TextBlock.Foreground="Black" BorderThickness="2" CornerRadius="5">
<!--添加Border元素,為其設定屬性-->
<Grid>
<!--添加矩形元素,将矩形設定成點劃線,預設是隐藏-->
<Rectangle Name="FocusRectangle" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1,2" SnapsToDevicePixels="True"></Rectangle>
<!--為Grid中添加ContentPresenter元素-->
<ContentPresenter Margin="{TemplateBinding Padding}" RecognizesAccessKey='True' HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</Border>
<!--設定屬性觸發器-->
<ControlTemplate.Triggers>
<!--設定一個滑鼠移動到元素上的效果(用IsMouseOver屬性)-->
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="DarkRed"></Setter>
<Setter TargetName="Border" Property="BorderBrush" Value="Red"></Setter>
</Trigger>
<!--設定一個點選元素的效果(用IsPressed屬性)-->
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="Yellow"></Setter>
</Trigger>
<!--設定IsKeyboardFocused屬性,将舉行顯示出來。-->
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusRectangle" Property="Visibility" Value="Visible"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<!--為第一個Button元素設定模闆。-->
<Button Template="{StaticResource button_template}" Padding="20" Margin="10" >我是Button1</Button>
<Button Template="{StaticResource button_template}" Padding="20" Margin="10" >我是Button2</Button>
<Button Padding="5" Margin="5" Height="50">我是Button2</Button>
</StackPanel>
效果圖:當點選了第二個圖檔時,出現虛線。
9、潤色按鈕。
就是當按鈕的IsEnabled=false的時候,設定背景色。這個時候需要設定IsEnabled屬性觸發器了。
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="TextBlock.Foreground" Value="gray"></Setter>
<Setter TargetName="Border" Property="Background" Value="MistyRose"></Setter>
</Trigger>
</ControlTemplate.Triggers>
<Button Template="{StaticResource button_template}" IsEnabled="False" Padding="5" Margin="10" Height="50">我是Button3</Button>
10、模闆與樣式。
模闆和樣式有類似之處,樣式和模闆都可以改變元素的外觀。然而,樣式被限制在一個小得多的範圍之内。一般情況下,模闆用于更改元素的外觀,樣式用于更改元素屬性。
11、使用事件觸發器(事件觸發器一般用于動畫)。
通過EventTrigger設定事件觸發器,通過RoutedEvent指定事件。一般事件處理器用于處理動畫。
<Window.Resources>
<!--定義一個控件模闆-->
<ControlTemplate x:Key="button_template" TargetType="{x:Type Button}">
<!--添加Border元素-->
<Border Name="Border" CornerRadius="5" BorderBrush="Orange" BorderThickness="3" Background="Azure">
<!--添加Grid元素-->
<Grid>
<Rectangle SnapsToDevicePixels="True" Visibility="Hidden" StrokeDashArray="1,2" StrokeThickness="1"></Rectangle>
<ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</Border>
<!--定義觸發器-->
<ControlTemplate.Triggers>
<!--定義一個事件觸發器(滑鼠移動到元素上),改變Border元素的背景色-->
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color">
<ColorAnimation Duration="0:0:0:1" To="Blue">
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<!--定義一個事件觸發器(滑鼠離開元素時發生),将Border元素的背景色改變成原來的背景色-->
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color">
<ColorAnimation Duration="0:0:0:0" To="Azure">
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<!--為圖檔應用模闆-->
<Button Template="{StaticResource button_template}" Padding="30" Margin="10" Width="150">我是Button1</Button>
<Button Template="{StaticResource button_template}" Padding="30" Margin="10" Width="150">我是Button2</Button>
<Button Template="{StaticResource button_template}" Padding="30" Margin="10" Width="150">我是Button3</Button>
</StackPanel>
12、組織模闆資源(将模闆定義在資源字典中)。
當使用控件模闆時,需要決定如何更廣泛地共享模闆,以及是否希望自動地或明确地應用模闆,但是要思考一個問題,将他們限定在特定的視窗中嗎?大多數情況下,控件模闆應用于多個視窗,甚至可能應用于整個應用程式中,為避免多次定義模闆,基本上都是定義在資源字典中,然後将他們合并到Application.Resource中,每個控件模闆建立單獨的資源字典,而不要把所有的模闆都定義在同一個資源字典中。
添加名叫ButtonDictionary.xaml的資源字典:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--定義一個名叫HighlightBackground的畫刷,用于設定滑鼠移動到元素上觸發的的IsMouseOver屬性,更改Border背景色-->
<RadialGradientBrush x:Key="HighlightBackground" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset=".4" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個名叫HighlightBackground的畫刷,用于設定滑鼠點選button時,觸發的IsPressed屬性,更改Border背景色。-->
<RadialGradientBrush x:Key="PressedBackground" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset="1" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個畫刷,目的用于設定Button按鈕的背景色-->
<SolidColorBrush x:Key="DefaultBackground" Color="Blue"></SolidColorBrush>
<!--定義一個畫刷,用于設定禁用按鈕的背景色-->
<SolidColorBrush x:Key="DisabledBackground" Color="Gray"></SolidColorBrush>
<!--定義一個畫刷,用于設定模闆中的Border元素的顔色。-->
<RadialGradientBrush x:Key="Border" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset="1" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個名叫ContentPresenter_Style的樣式,用于更改模闆中的樣式,将字型顔色變成白色。-->
<Style x:Key="ContentPresenter_Style">
<Setter Property="Control.Foreground" Value="White"></Setter>
</Style>
<!--定義個模闆-->
<ControlTemplate x:Key="GradientTemplate" TargetType="{x:Type Button}">
<Border Name="Border" BorderBrush="{StaticResource ResourceKey=Border}" BorderThickness="2" CornerRadius="2" Background="{StaticResource ResourceKey=DefaultBackground}">
<Grid>
<Rectangle Name="FocusRectangle" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1,2" SnapsToDevicePixels="True"></Rectangle>
<ContentPresenter Name="cp" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"></ContentPresenter>
</Grid>
</Border>
<!--定義模闆觸發器-->
<ControlTemplate.Triggers>
<!--定義屬性觸發器(滑鼠移動到元素上)-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=HighlightBackground}"></Setter>
<Setter TargetName="cp" Property="Style" Value="{StaticResource ResourceKey= ContentPresenter_Style}"></Setter>
</Trigger>
<!--定義屬性觸發器(點選元素時觸發)-->
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=PressedBackground}"></Setter>
</Trigger>
<!--定義屬性觸發器(擷取焦點)-->
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusRectangle" Property="Visibility" Value="Visible"></Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=DisabledBackground}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ResourceDictionary>
将資源字典合并到App.xaml檔案中的<Application.Resources>節點中。
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonDictionary.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
在視窗中引用:
<StackPanel>
<Button Template="{StaticResource GradientTemplate}" Padding="30" Margin="10" Width="150">我是Button1</Button>
<Button Template="{StaticResource GradientTemplate}" Padding="30" Margin="10" Width="150">我是Button2</Button>
<Button Template="{StaticResource GradientTemplate}" IsEnabled="False" Padding="30" Margin="10" Width="150">我是Button3</Button>
</StackPanel>
13、通過樣式應用模闆。
就是在ButtonDictionary.xaml檔案中添加一個style樣式,為樣式設定模闆屬性,然後值指向定義的模闆,然後在視窗中設定元素的style屬性指向ButtonDictionary.xaml檔案中定義的樣式即可。
在ButtonDictionary.xaml檔案中添加Style樣式:
<!--添加名叫Button_Style的樣式,設定Template屬性,值指向定義的模闆-->
<Style x:Name="Button_Style" TargetType="{x:Type Button}">
<Setter Property="Template" Value="{StaticResource ResourceKey=GradientTemplate}"></Setter>
</Style>
在視窗中引用樣式:
<StackPanel>
<!--在這個地方是為元素設定樣式,而不是通過模闆哦--->
<Button Style="{StaticResource Button_Style}" Padding="30" Margin="10" Width="150">我是Button1</Button>
<Button Padding="30" Margin="10" Width="150">我是Button2</Button>
<Button Style="{StaticResource Button_Style}" IsEnabled="False" Padding="30" Margin="10" Width="150">我是Button3</Button>
</StackPanel>
14、自動應用模闆。
也是在ButtonDictionary.xaml中添加一個Style樣式,然後為其設定TargetType屬性,不要為其指定x:key特性即可。應用模闆不可以自動應用到元素上了。
<!--添加Style樣式,設定模闆屬性,值等于上面定義的模闆。不用為其指定x:key特性就會自動應用到Button元素上了-->
<Style TargetType="{x:Type Button}">
<Setter Property="Control.Template" Value="{StaticResource GradientTemplate}"></Setter>
</Style>
視窗中不用引用,就會自動應用了:
<StackPanel>
<Button Padding="30" Margin="10" Width="150">我是Button1</Button>
<Button Padding="30" Margin="10" Width="150">我是Button2</Button>
<Button IsEnabled="False" Padding="30" Margin="10" Width="150">我是Button3</Button>
</StackPanel>
15、皮膚。
在一些應用程式中,可能希望動态地改變模闆,比如通常所說的皮膚。基本技巧是運作時加載新的資源字典,并使用新加載的資源字典替代目前的資源字典(不需要替換所有資源,隻需要替換那些用于皮膚的資源)。主要用于檢索ResourceDictionary對象,該對象經過編譯并作為資源嵌入到應用程式中。
16、建構更複雜的模型。
嵌套的模闆:
<Window x:Class="嵌套的模型.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!--定義一個名叫HighlightBackground的畫刷,用于設定滑鼠移動到元素上觸發的的IsMouseOver屬性,更改Border背景色-->
<RadialGradientBrush x:Key="HighlightBackground" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset=".4" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個名叫HighlightBackground的畫刷,用于設定滑鼠點選button時,觸發的IsPressed屬性,更改Border背景色。-->
<RadialGradientBrush x:Key="PressedBackground" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset="1" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個畫刷,目的用于設定Button按鈕的背景色-->
<SolidColorBrush x:Key="DefaultBackground" Color="Blue"></SolidColorBrush>
<!--定義一個畫刷,用于設定禁用按鈕的背景色-->
<SolidColorBrush x:Key="DisabledBackground" Color="Gray"></SolidColorBrush>
<!--定義一個畫刷,用于設定模闆中的Border元素的顔色。-->
<RadialGradientBrush x:Key="Border" RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset="1" Color="Blue"></GradientStop>
</RadialGradientBrush>
<!--定義一個名叫ContentPresenter_Style的樣式,用于更改模闆中的樣式,将字型顔色變成白色。-->
<Style x:Key="ContentPresenter_Style">
<Setter Property="Control.Foreground" Value="White"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="Hello,World" Height="80" Margin="10">
<Button.Style>
<Style>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="Border" BorderBrush="{StaticResource ResourceKey=Border}" BorderThickness="2" CornerRadius="2" Background="{StaticResource ResourceKey=DefaultBackground}">
<Grid>
<Rectangle Name="FocusRectangle" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1,2" SnapsToDevicePixels="True"></Rectangle>
<ContentPresenter Name="cp" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--定義屬性觸發器(滑鼠移動到元素上)-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=HighlightBackground}"></Setter>
<Setter TargetName="cp" Property="Style" Value="{StaticResource ResourceKey= ContentPresenter_Style}"></Setter>
</Trigger>
<!--定義屬性觸發器(點選元素時觸發)-->
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=PressedBackground}"></Setter>
</Trigger>
<!--定義屬性觸發器(擷取焦點)-->
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusRectangle" Property="Visibility" Value="Visible"></Setter>
<Setter TargetName="Border" Property="Background" Value="Yellow"></Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ResourceKey=DisabledBackground}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Window>
17、圓角圖檔。
<Border BorderBrush="Red" BorderThickness="2" Margin="10" Width="202" Height="202" CornerRadius="5">
<Grid Width="200" Height="200" Margin="-1,-1,0,0">
<Border Name="myBorder" CornerRadius="5" Background="White"/>
<Image Source="1.jpg" Margin="1" Stretch="Fill">
<Image.OpacityMask>
<VisualBrush Visual="{Binding ElementName=myBorder}"/>
</Image.OpacityMask>
</Image>
</Grid>
</Border>
End。