天天看點

控件模闆

原文: 控件模闆

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>      

邏輯樹:

控件模闆

可視化樹:

控件模闆

建立一個名叫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。

控件模闆

繼續閱讀