访问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可以看到,但是别人就是看不到,气人啊-没 ...
随机推荐
- Session的获得方式
在hibernate.cfg.xml中添加这个属性,来开启currentSession的使用<property name= "hibernate.current_session_con ...
- 【英语】Bingo口语笔记(59) - 穿着的表达
- 【英语】Bingo口语笔记(78) - let系列
- oracle interval-partition 解决range分区大难题
博客<oracle分区>中讲了oracle的几种分区,并且对于oracle的典型分区如Range分区和List分区给了示例. 在实际运用Range分区时,遇到了这样的难题: createt ...
- 《Unix网络编程》卷2 读书笔记 第2章- Posix IPC
1. 概述 Posix IPC 包括:Posix消息队列.Posix信号量.Posix共享内存区 Posix IPC在访问它们的函数和描述它们的信息上有一些类似点. 本章讲述所有这些共同属性:用于标识 ...
- 【UVa-514】铁轨——栈的学习
UVa514 Rails(铁轨) 题目:铁轨 题目链接: UVa514链接 题目描述: 某城市有一个火车站,有n节车厢从A方向驶入车站,按进站的顺序编号为1-n.你的任务是判断是否能让它们按照某种特定 ...
- Shell教程4-Shell替换
如果表达式中包含特殊字符,Shell 将会进行替换.例如,在双引号中使用变量就是一种替换,转义字符也是一种替换. 举个例子: 复制纯文本新窗口 #!/bin/bash a=10 echo -e & ...
- AutoCompleteTextView不能使用的问题
AutoCompleteTextView按照网络上的方法写之后不能使用 解决方法: android:layout_width="fill_parent" 而不能是wrap_pare ...
- Kyoto Cabinet(DBM) + Kyoto Tycoon(网络层)
项目原地址kyotocabinet: http://fallabs.com/kyotocabinet/ kyototycoon: http://fallabs.com/kyototyc ...
- C# 导出一个控件的矢量图
调用Control.DrawToBitmap(Bitmap) 方法是很容易得到控件的图形的. 但是bitmap是栅格化图形.栅格化图形有很多缺点,比如文件体积比较大. 放大后失真. 不易编辑等等. 这 ...