访问ControlTemplate内部的元素
需要用到code behind
注意要给需要访问的元素命名x:Name="PART_TextBlock"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControlLib"> <Style TargetType="{x:Type local:MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel>
<TextBlock x:Name="PART_TextBlock" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
custom control的程序部分 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace CustomControlLib
{ public class MyControl : Button
{
private const string TextBlockPart = "PART_TextBlock";
TextBlock textBlock;
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
}
public override void OnApplyTemplate() //OnApplyTemplate get called everytime a template is applied to the control,control update
{
base.OnApplyTemplate(); //Button有自己的OnApplyTemplate我们需要call这个beofre call我们自己写的OnApplyTemplate方法
if (textBlock != null) //避免memory leak每次call OnApplyTemplate方法时都给同一个textBlock加上event
{
textBlock.TextInput -= new TextCompositionEventHandler(textBlock_TextInput);
} textBlock = GetTemplateChild(TextBlockPart) as TextBlock;
if (textBlock != null)
{
textBlock.Text = "Set from code";
textBlock.TextInput +=new TextCompositionEventHandler(textBlock_TextInput);
} } private void textBlock_TextInput(object sender, TextCompositionEventArgs e)
{ }
}
}
使用该control
<Window x:Class="CustomControlDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:CustomControlLib;assembly=CustomControlLib"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<cc:MyControl />
</Grid>
</Window>
改进:上面的方法不好,设想如果controlTemaplte里有很多element都需要访问,每一个元素都需要后台程序这样访问的话,会很乱
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace CustomControlLib
{
[TemplatePart(Name = TextBlockPart, Type = typeof(TextBlock))] //告诉使用template的作者这里x:Name为PART_TextBlock的control一定要是TextBlock类型的
public class MyControl : Button
{
private const string TextBlockPart = "PART_TextBlock";
TextBlock _textBlock; //避免每一次call OnApplyTemplate都在方法体里创建一个TextBlock,在方法前定义一个变量来储存
protected TextBlock TextBlock
{
get {return _textBlock; }
set
{
if (_textBlock != null) //避免memory leak每次call OnApplyTemplate方法时都给同一个textBlock加上event
{
_textBlock.TextInput -= new TextCompositionEventHandler(textBlock_TextInput);
} _textBlock = value; if (_textBlock != null)
{
_textBlock.Text = "Set from code";
_textBlock.TextInput += new TextCompositionEventHandler(textBlock_TextInput);
}
}
}
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
}
public override void OnApplyTemplate() //OnApplyTemplate get called everytime a template is applied to the control,control update
{
base.OnApplyTemplate(); //Button有自己的OnApplyTemplate我们需要call这个beofre call我们自己写的OnApplyTemplate方法 TextBlock = GetTemplateChild(TextBlockPart) as TextBlock; //每次call都赋值属性
} private void textBlock_TextInput(object sender, TextCompositionEventArgs e)
{ }
}
}
TemplatePart(Name="PART_Decrease", Type=typeof(RepeatButton))
一直没明白这是干嘛用的,搜了一下,记载一下。
以Button的定义为例:

namespace System.Windows.Controls
{
// Summary:
// Represents a button control, which reacts to the Click event.
[TemplatePart(Name = "Normal State", Type = typeof(Storyboard))]
[TemplatePart(Name = "MouseOver State", Type = typeof(Storyboard))]
[TemplatePart(Name = "RootElement", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "Pressed State", Type = typeof(Storyboard))]
[TemplatePart(Name = "FocusVisualElement", Type = typeof(UIElement))]
[TemplatePart(Name = "Disabled State", Type = typeof(Storyboard))]
public class Button : ButtonBase
{
// Summary:
// Initializes a new instance of the Button class.
public Button();
// Summary:
// Apply a template to the Button.
protected override void OnApplyTemplate();
//
// Summary:
// Called when the IsEnabled property changes.
//
// Parameters:
// isEnabled:
// New value of the IsEnabled property.
protected override void OnIsEnabledChanged(bool isEnabled);
}
}

[TemplatePart(Name = "Normal State", Type = typeof(Storyboard))] 这种东东是做什么用的 , 其实这是一种契约 , 是一种推荐的控件设计模式(只是推荐) , 意思是告诉要来写ControlTemplate的用户 , 你的ControlTemplate中需要有一个x:Name为“Normal State” , 类型为Storyboard , 当然这个类型可以是继承来的, 为什么一定要包含这些契约规定的元素 , 因为逻辑部分对这些东西进行了引用,它们将对控件的默认行为起着关键作用, 可以理解为这个控件的最基本元素 , 是实现默认行为的最小集合, 自然,你的ControlTemplate中如果没有包含契约中的内容 , 则相应的逻辑将无法实现。
所以说白了,就是提示用的.....这么写比较规范。
访问ControlTemplate内部的元素的更多相关文章
- Div 内部所有元素 全部垂直对齐
http://stackoverflow.com/questions/7273338/how-to-vertically-align-an-image-inside-div How it works: ...
- C++ multimap容器访问同一键值元素的不同方法
multimap是一种多元map容器,允许一个键对应多个值. 本文介绍了 multimap访问同一键值元素的三种不同方法,详细看下面代码: typedef multimap<string,int ...
- WPF如何得到一个在用户控件内部的元素的坐标位置
例如有这样一个用户控件: <UserControl d:DesignHeight="100" d:DesignWidth="200" ...> &l ...
- Arduino内部网页代理,网页穿透,公网访问Arduino内部网页
#include <ESP8266WiFi.h> const char* id = "id"; //http://www.mcunode.com/proxy/ ...
- 访问树中的所有元素(DOM)
创建一个函数,给定页面上的DOM元素,将访问元素本身及其所有后代(而不仅仅是它的直接子代).对于访问的每个元素,函数应将该元素传递给提供的回调函数. 函数的参数应该是: 一个DOM元素 一个回调函数( ...
- vue学习(五) 访问vue内部元素或者方法
//html <div id="app"> <input type="button" value="ok" v-bind: ...
- Windows Store App 访问应用内部文件
访问应用程序内部的文件可以使用多种不同的方法,13.1节中已经介绍过相关的方法,除此之外,还可以使用文件的URI地址直接对文件进行检索,这种访问方式需要用到StorageFile类的静态方法GetFi ...
- 兼容性背景颜色半透明CSS代码(不影响内部子元素)
如何简单兼容性的实现父元素是半透明背景色,而子元素不受影响. 兼容所有浏览器的背景颜色半透明CSS代码: background-color: rgba(, , , .); filter: progid ...
- internet访问局域网内部方法之----------路由器端口映射
很多人每天都问为什么要端口映射?例如:通过路由器上网的,网站自己可以访问,但是别人就不能:输入127.0.0.1可以访问,别人还是看不到:输入localhost可以看到,但是别人就是看不到,气人啊-没 ...
随机推荐
- LA 3635 Pie 派 NWERC 2006
有 f + 1 个人来分 n 个圆形派,每个人得到的必须是一整块派,而不是几块拼在一起,并且面积要相同.求每个人最多能得到多大面积的派(不必是圆形). 这题很好做,使用二分法就OK. 首先在读取所有派 ...
- JQuery开发之Galleriffic图片插件介绍
Galleriffic是一个用于创建快速展示相册中照片的jQuery插件.从图一中可以看成,图片既可以以幻灯片的方式查看,也可以手动点击缩略图查看.Galleriffic还支持分页,从而使得它能够展示 ...
- C#隐式运行CMD命令(隐藏命令窗口)
原文 C#隐式运行CMD命令(隐藏命令窗口) 本文实现了C#隐式运行CMD命令的功能.下图是实例程序的主画面.在命令文本框输入DOS命令,点击"Run"按钮,在下面的文本框中输出运 ...
- Python自动单元测试框架
原文链接:http://www.ibm.com/developerworks/cn/linux/l-pyunit/ 软件的测试是一件非常乏味的事情,在测试别人编写的软件时尤其如此,程序员通常都只对编写 ...
- 【转】loadrunner检查点设置
转自:http://www.cnblogs.com/fnng/archive/2013/03/10/2953257.html 判断脚本是否执行成功是根据服务器返回的状态来确定的,如果服务器返回的HTT ...
- C# 实现无焦点窗体(转载)
#region 无焦点窗体 [System.Runtime.InteropServices.DllImport("user32.dll")] private extern stat ...
- Spring Boot 学习笔记 - 认识Spring Boot框架
因各种原因,.NET前端工程师重新接触JAVA,真是向全栈的路上又迈出了无奈的一步. 下面正文: Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初 ...
- Winform後台如何動態修改App.config文件里的內容
以下方法修改的,自己添加的app.config裡面不會顯示出修改的東西. 方法一:通過使用System.Xml.XmlDocument對象的方法進行bin\debug\~.vshost.exe.Con ...
- php连接数据库
<?php header('Content-Type:text/html; charset=utf-8'); define('DB_HOST', 'localhost'); define('DB ...
- 一款APP从设计稿到切图过程全方位揭秘 Mark
纯干货!一款APP从设计稿到切图过程全方位揭秘 @BAT_LCK:我本身是一名GUI设计师,所以我只站在GUI设计师的角度去把APP从项目启动到切片输出的过程写一写,相当于工作流程的介绍吧.公司不 ...