惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
Simon Willison's Weblog
Simon Willison's Weblog
H
Help Net Security
F
Fortinet All Blogs
H
Heimdal Security Blog
S
Schneier on Security
L
LangChain Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
NISL@THU
NISL@THU
P
Palo Alto Networks Blog
J
Java Code Geeks
博客园 - 【当耐特】
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Vulnerabilities – Threatpost
I
InfoQ
Recorded Future
Recorded Future
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
CERT Recently Published Vulnerability Notes
T
Tenable Blog
腾讯CDC
C
Check Point Blog
量子位
M
MIT News - Artificial intelligence
GbyAI
GbyAI
罗磊的独立博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog
小众软件
小众软件
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
V2EX - 技术
V2EX - 技术
T
Threatpost
Engineering at Meta
Engineering at Meta
Attack and Defense Labs
Attack and Defense Labs
T
Tailwind CSS Blog
S
Securelist
The Cloudflare Blog
博客园 - 叶小钗
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
爱范儿
爱范儿

博客园 - 赖仪灵

分享几个简单的WPF控件(代码) 捕捉WPF应用程序中XAML代码解析异常 设置WPF窗口相对于非WPF窗口的位置 上海.NET俱乐部--微软社区巡展VSTS上海专题活动 WPF关于WindowInteropHelper的一个BUG WPF全景体验 最优化WPF 3D性能(基于“Tier-2”硬件) Windows Vista桌面窗口管理器(3) 闲话WPF之二六(WPF性能优化点) 闲话WPF之二四(WPF中的ControlTemplate [2]) Windows Vista桌面窗口管理器(2) 闲话WPF之二三(WPF中的ControlTemplate [1]) 闲话WPF之二二(WPF中的Style) Windows Vista桌面窗口管理器(1) 闲话WPF之二一(WPF中的数据处理 [3]) 闲话WPF之二十(WPF中的传递事件 [2] ) 闲话WPF之十九(WPF中的传递事件 [1] ) 闲话WPF之十八(WPF中的资源 [4] ) 闲话WPF之十七(WPF中的资源 [3])
闲话WPF之二五(WPF中的ControlTemplate [3])
赖仪灵 · 2007-01-18 · via 博客园 - 赖仪灵

在实际应用中,ControlTemplate是一个非常重要的功能。它帮助我们快速实现很Cool的自定义控件。下面我以Windows Vista SDK中的例子ControlTemplateExamples为基础,简单地分析ControlTemplate的使用。这个例子工程非常丰富,几乎包含了所有的标准控件。所以,在实现自定义控件时,可以先参考这样进行适当的学习研究。

首先是App.xaml文件,这里它把Application.StartupUri属性设置为Window1.xaml。然后把工程目录Resource下所有的控件xaml文件都合成为了应用程序范围内的资源。

<Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Resources\Shared.xaml" />
        <!-- 这里省略 -->
        <ResourceDictionary Source="Resources\NavigationWindow.xaml" />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

这样的用法很有借鉴意义。在WPF中实现Skin框架也随之变得非常简单。值需要动态使用不同的XAML文件即可。然后是Window1.xaml文件。它里面几乎把所有的控件都显示了一遍。没有什么多说的。重点看Resource目录下的自定义控件文件。这里的控件太多,不可能每个都说说。我只挑选其中的Button.xaml为例:

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

  <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Shared.xaml"/>
  </ResourceDictionary.MergedDictionaries>

  <!-- Focus Visual -->

  <Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
      <Setter.Value>
        <ControlTemplate>
          <Border>
            <Rectangle Margin="5" StrokeThickness="3"
            Stroke="#60000000" StrokeDashArray="4 2"/>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
  <!--...............-->
</ResourceDictionary>

因为这个XAML文件作为资源使用,所以其根元素是ResourceDictionary,而不再是Window/Application等等。同时,资源文件也可以相互的嵌套,比如上面的包含的Shared.xaml文件。然后定义了一个Style,注意这里的目标类型为Control.Template,也就是针对所有的控件模板有效,所以Style添加了一个x:Key属性。这样就阻止Style适用于当前的所有控件。我们必须显式的引用这个Style。相关内容,可以参考我前面的Style文章

另一个需要说明的是<ControlTemplate>的子元素,可以是任何的VisualTree。比如这里的Border,也可以是Grid等等。好了,现在定义了一个名为ButtonFocusVisual的模板,下面只需要引用它即可。

<Style TargetType="Button">
    <!--.............-->
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <!--.............-->
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">

          <Border x:Name="Border" ......./>

          <ControlTemplate.Triggers>
            <Trigger Property="IsKeyboardFocused" Value="true">
              <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DefaultedBorderBrush}" />
            </Trigger>           
          </ControlTemplate.Triggers>

        </ControlTemplate>
      </Setter.Value>
    </Setter>
</Style>

这是真正影响控件外观的代码。因为在定义Style的时候没有指定具体的x:Key,所以将影响所有的Button。如你所见,在FocusVisualStyle这个属性(类型是Style)上我们用资源方式引用了前面定义的命名Style:ButtonFocusVisual。接下来是定义Template,并为其子元素Border定义了一个名称。然后就是ControlTemplate的触发器。在IsKeyboardFocused属性满足条件的情况下,我们把Border(注意这个Border不是类型,而是具体的某个对象)的BorderBrush修改为另一个静态资源。结合前面的Post,理解也就不难了。

最后,我们还会发现一个有趣的问题:这个例子虽然是ControlTempalte,但工程名称却是SimpleStyle,从这一点我们也可以看出:Style和Template通常是配合使用才能真正的实现丰富的自定义功能。