控件模板(代码片段)

lonelyxmas lonelyxmas     2022-12-22     480

关键词:

原文:控件模板

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。

技术分享图片


控件模板(代码片段)

原文:控件模板1、理解逻辑树与可视化树。添加的元素分类称之为逻辑树,可视化树是逻辑树的扩展版本,目的用于将元素分成更小的部分。WPF提供了用于浏览逻辑树和可视化树的两个类:System.Windows.LogicalTreeHelper和System.Windows.Me... 查看详情

uwp查找模板中的控件(代码片段)

原文:UWP查找模板中的控件这个标题我也不知道咋起,意思说一下你就明白。1.对官方控件的模板进行定制修改,以满足多样化需求,还有漂亮的UI比如ListView,GridView等。2.在设计的情况下并没有这个控件,而在运行时的时候出现... 查看详情

wpf学习—模板(代码片段)

...e分为两大类:1.ControlTemplate是算法内容的表现形式,控制控件的内部结构。决定控件“长成什么样子”,并让程序员有机会在控件原有的内部逻辑基础上扩展自己的逻辑2.DataTemplate是数据内容的表现形式,决定数据显示,是简单... 查看详情

gridview合并单元格万能版(包括模板列)(代码片段)

...信息的行(单元格)包含模板列根据ID=rowspanid的hiddenfield控件的值来合并。需要合并的单元格需加上这个控件。根据控件值合并 查看详情

xml适用于windows8.1和windowsphone8.1应用程序的扩展器控件的模板。(代码片段)

查看详情

2021-09-12wpf上位机08-数据模板(代码片段)

...:数据模板DataTemplate:数据的外衣可以定制ControlTemplate:控件的显示外衣可以定制ItemsPanelTemplate:集合控件的子项排列方式可以定制1、数据模板的定义与使用2、数据模板选择器DataTemplateSelector二:相关案例<Windowx:Class="Zhaoxi.Tem... 查看详情

wpf模板应用(代码片段)

...emsPanelTemplate,DataTemplate.其中ControlTemplate和ItemsPanelTemplate是控件模板,DataTemplate是数据模板,他们都派生自FrameworkTempla 查看详情

wpf中通过代码定义模板(代码片段)

...随时动态的去操作,而在XAML中定义的一般都是静态的。//控件呈现的显示内容1(这里为Image)FrameworkElementFactoryfe=newFrameworkElementFactory(typeof(Image),"Image");Bi 查看详情

xaml:自定义控件中事件处理的最佳实践(代码片段)

原文:XAML:自定义控件中事件处理的最佳实践在开发XAML(WPF/UWP)应用程序中,有时候,我们需要创建自定义控件(CustomControl)来满足实际需求。而在自定义控件中,我们一般会用到一些原生的控件(如Button、TextBox等)来辅助以完成自... 查看详情

word内容控件属性编辑(代码片段)

...自己一份word模板,基于统一性,里面包含了很多“内容控件”,一般情况下,只需要根据内容控件进行编辑即可,但如果想对内容控件本身做编辑操作,例如删除等。操作:单击文件>选项>自定义功能区。在选项卡,在自定... 查看详情

不修改模板的前提下修改visualstate中的某些值(代码片段)

...某些值-超威蓝火UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,BorderBrush,而控件一般至少具有Normal、PointerOver、Pressed、Disabled,ItemContainerStyle还有Selected、PointerOverSelected、PressedSelected这几... 查看详情

不修改模板的前提下修改visualstate中的某些值(代码片段)

UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,BorderBrush,而控件一般至少具有Normal、PointerOver、Pressed、Disabled,ItemContainerStyle还有Selected、PointerOverSelected、PressedSelected这几种。那么常规方法... 查看详情

2021-10-14wpf上位机67-自定义控件(代码片段)

自定义控件1、结构说明2、样式模板[Windows主题相关]Themes目录名称不能修改Generic.xaml可以修改,并不是随意修改3、视觉状态(不是自定义控件独有用户控件也可以用).NETCore开源的代码里面移除这块内容4、关键特性TemplatePart、Tem... 查看详情

c#winformdatagridview控件的基本使用(代码片段)

▲运行截图两个注意点报错:DataGridView控件中至少有一列没有单元格模板解决方法:一个小误区,你看看设计窗体生成的代码,DataGridView的列不是GridViewColumn而是DataGridViewTextBoxColumn你只要添加这个类型的对象就可以了,我也是饶... 查看详情

如何从代码隐藏中访问控件模板的元素

】如何从代码隐藏中访问控件模板的元素【英文标题】:HowdoIaccessanelementofacontroltemplatefromwithincode-behind【发布时间】:2011-12-2822:16:18【问题描述】:我正在尝试访问内容控件的控件模板内的用户控件。具体来说:<ContentControlx:N... 查看详情

qt功能优化:电子钟模板(代码片段)

Qt功能优化:电子钟模板(文章目录)一、效果图LCDNumber控件显示时间:二、使用步骤1..h部分#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>#include<QDate>namespaceUiclassMainWindow;classMainWindow:publicQMainWindowQ_O 查看详情

wpf自定义控件的三种方式(代码片段)

简介: 某些场景下,我们确实需要创建新的控件。此时,理解WPF不同控件的创建方法就显得非常重要。WPF提供3个用于创建控件的方法,每个方法都提供不同的灵活度。WPF控件可以通过数据模型(DataTemplateÿ... 查看详情

组件与模板显示数据(代码片段)

在Angular中最典型的数据显示方式,就是把HTML模板中的控件绑定到Angular组件的属性。带有双花括号的插值表达式(interpolation) 来显示一个组件属性。用 ngFor 显示数组。用一个TypeScript类来为你的组件描述模型数据并显示... 查看详情