当前位置: 首页 > news >正文

控件模板

控件模板
原文: 控件模板

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、构建更复杂的模型。

嵌套的模板:

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">    
    <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、圆角图片。

xaml代码:

<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。

posted on 2018-08-15 00:22 NET未来之路 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/9479031.html

相关文章:

  • php 热点,PHP+jQuery实现中国地图热点数据统计展示效果
  • phpspy.php,一款php后门 phpspy的情况
  • Appium 之处理首次启动手机App时的系统权限弹框
  • 体对角线 matlab,Matlab计算结果显示求不出精确解
  • 数据库ACID操作---事务四原则
  • php html转pdf 简书,Laravel Html 导出 PDF 方案 ----- wkhtmltopdf laravel-snappy
  • aps.net的身份证背景图片
  • matlab怎么画lnx图像,inx图像(lnx的图像函数)
  • matlab计算结果中特别长,matlab运算结果太长Output truncated. Text exceeds maximum line length o......
  • java之注解
  • php 参数 过滤 类,参数过滤类
  • 还是畅通工程(HDU 1233)
  • mysql多表查询基础命令,MySql多表查询命令
  • B - Battle City bfs+优先队列
  • python中使用关键字声明一个函数,Python函数的说明与运用
  • 30天自制操作系统-2
  • golang 发送GET和POST示例
  • js学习笔记
  • markdown编辑器简评
  • vue自定义指令实现v-tap插件
  • webpack项目中使用grunt监听文件变动自动打包编译
  • windows下mongoDB的环境配置
  • Zsh 开发指南(第十四篇 文件读写)
  • 分享几个不错的工具
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 用jquery写贪吃蛇
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • ​iOS安全加固方法及实现
  • #Linux(帮助手册)
  • (pytorch进阶之路)扩散概率模型
  • (阿里云万网)-域名注册购买实名流程
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .java 9 找不到符号_java找不到符号
  • .NET Core WebAPI中封装Swagger配置
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .net web项目 调用webService
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [ 第一章] JavaScript 简史
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • []error LNK2001: unresolved external symbol _m
  • [APIO2012] 派遣 dispatching
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
  • [fsevents@^2.1.2] optional install error: Package require os(darwin) not compatible with your platfo
  • [IE9] IE9 Beta崩溃问题解决方案
  • [iOS]-UIKit
  • [java/jdbc]插入数据时获取自增长主键的值
  • [PHP源码阅读]empty和isset函数
  • [pyqt5]PyQt5窗体背景图片拉伸填充