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

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

  • 相关阅读:
    Virtual Box的一些东西
    sun 的Virtual box
    Powerdesigner的vbscript
    MemoryStream的一些问题
    vs2008 三大形象代言人
    ASP.NET学习之匿名方法
    asp.net2.0学习历程 菜鸟到中级程序员的飞跃
    ASP.NET程序员必看书
    设计模式学习扎马步
    MDI窗体改变背景
  • 原文地址:https://www.cnblogs.com/shawnzxx/p/3262095.html
Copyright © 2020-2023  润新知