需要用到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中如果没有包含契约中的内容 , 则相应的逻辑将无法实现。

所以说白了,就是提示用的.....这么写比较规范。

转载于:https://www.cnblogs.com/shawnzxx/p/3262095.html

访问ControlTemplate内部的元素相关推荐

  1. linux访问网页元素,Linux_DOM和JAVASCRIPT访问页面上的元素,访问方法:getElementById() - phpStudy...

    DOM和JAVASCRIPT访问页面上的元素 访问方法: getElementById():返回拥用传递给该方法的指定id的第一个对象的引用. getElementsByName():返回拥用传递该方 ...

  2. SpringBoot中访问Thymeleaf提示:元素类型 meta 必须由匹配的结束标记终止。

    场景 新建SpringBoot项目后整合Thymelaf后访问页面提示: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止. ...

  3. 用JS访问iframe中的元素

    用JS访问iframe中的元素 1.首先,如何访问iframe中的元素?见如下代码: (1)1.htm源码: <input  type=button value="test" ...

  4. STL 容器和迭代器连载8_访问顺序容器的元素

    2019独角兽企业重金招聘Python工程师标准>>> /*- ========================================================== ...

  5. 【matlab】访问结构体内部元素

    [matlab]访问结构体内部元素 语法格式: 结构体名称.字段名: 如果给域换新值则: 结构体名称.字段名=新值: 例如:person.weight; 具体情况我们看一下代码: >> s ...

  6. jQuery 学习-DOM篇(二):jQuery 在 DOM 内部插入元素

    推荐阅读 Helm3(K8S 资源对象管理工具)视频教程:https://edu.csdn.net/course/detail/32506 Helm3(K8S 资源对象管理工具)博客专栏:https: ...

  7. 【云原生 • Kubernetes】认识 k8s 网络、外部网络访问 k8s 内部服务

    目录 一.认识 Kubernetes 网络 二.外部网络如何访问 k8s 内部服务 1. NodePort 2. Load Balancer 3. Ingress 一.认识 Kubernetes 网络 ...

  8. teamviewer v_p_n+xp v_p_n服务实现在家访问公司内部局域网

    原文地址:teamviewer v_p_n+xp v_p_n服务实现在家访问公司内部局域网 我的需求与作者是一样一样的,公司工作机IP为172.16.136.x,公司服务器IP有172.16.136. ...

  9. 华为WeLink钉钉企业微信飞书等,通过竹云IDaaS,访问企业内部应用及SaaS应用

    背景@TOC 钉钉.企业微信.飞书.华为WeLink等,通过竹云IDaaS,访问企业内部应用及SaaS应用 背景 随着移动办公的需求,华为WeLink.钉钉.企业微信.飞书等移动办公App在各行各业中 ...

  10. 基于C#的AutoCAD二次开发之获取用户输入信息、选择集、访问CAD内部命令

    基于C#的AutoCAD二次开发之获取用户输入信息.选择集.访问CAD内部命令 在CAD创建图形对象时,经常需要和用户进行交互,例如:直线创建时需要用户输入起点和终点(或长度)信息,复制对象时需要指定 ...

最新文章

  1. JVM与Dalvik
  2. 强制杀oracle进程
  3. 19、任务十八——事件委托、数组处理
  4. 计算机公开课教学反思,语文公开课教学反思
  5. LeetCode 656. 金币路径(DP)
  6. tensorflow基础:tf.data.Dataset.from_tensor_slices() 与 tf.data.Dataset.from_generator()的异同
  7. 轻量级的移动开发JavaScript框架-zepto.js
  8. JAVA毕设项目图书馆预约占座系统(java+VUE+Mybatis+Maven+Mysql)
  9. 工程图学与计算机绘图考查,工程图学与计算机绘图
  10. 计算机老出现安全警报怎么办,windows安全警报怎么关闭,教您怎么关闭windows安全警报...
  11. Solidity语言详解——view和pure函数的使用区别
  12. python正则匹配连续相同字符_正则表达式: 匹配n个相同连续字符
  13. @RunWith和@ContextConfiguration的用法
  14. 『转』为什么中国的程序员总被称为码农?
  15. Mysql隔离级别、锁及死锁
  16. 省钱第一步,华为云为您服务|和车神哥一起薅羊毛
  17. 《C语言程序设计(第三版)》苏小红 习题六 答案
  18. JavaScript 模块化介绍
  19. 电子会议桌牌或将替代纸质桌牌标签
  20. 国内的Internet九大骨干网是哪些网络

热门文章

  1. 七日Python之路--第十一天
  2. 蓝桥杯“基础练习: 十六进制转十进制
  3. 用arp-scan扫描局域网IP地址
  4. android studio actionbar,Android Studio环境下ActionBar的使用教程以及如何解决遇到的问题...
  5. python使用struct处理二进制数据(使用pack和unpack进行打包和解包)
  6. html里面怎么引入swiper,JavaScript库——使用swiper.js创建嵌套的swiper
  7. java r日历系统_Java GrerorianCalendar 实现日历查询
  8. python装饰器两层和三层_2020 python学习第十六天————三层装饰器与迭代器
  9. [转载]Java多线程——创建线程池的几个核心构造参数
  10. select2 清除已选项