一文带你了解WPF中的附加事件

目录
  • 什么是附加事件
  • 附加事件用法
  • Microsoft 官方文档
  • 附加事件案例
    • 定义自定义控件
    • 注册使用附加事件

什么是附加事件

Microsoft 官方概述:

附加事件可用于在非元素类中定义新的 路由事件 ,并在树中的任何元素上引发该事件。 为此,必须将附加事件注册为路由事件,并提供支持附加事件功能的特定 支持代码 。 由于附加事件注册为路由事件,因此在元素树中引发时,它们会传播到元素树中。

简单来说就是,可以进行附加操作的事件,必须为路由事件(RoutedEvent)。

附加事件用法

在 XAML 语法中,附加事件由其 事件名称和所有者 类型指定,格式为 <owner type>.<event name>。 由于事件名称使用其所有者类型的名称进行限定,因此语法允许事件附加到任何可以实例化的元素。 此语法也适用于附加到事件路由中任意元素的常规路由事件的处理程序。

Microsoft 官方文档

这里简略的借用文档中的说明,详细学习请以文档为准:附加事件概述 (WPF .NET)

附加事件案例

定义自定义控件

using System.Windows;
using System.Windows.Controls;

namespace assembly
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:assembly"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:assembly;assembly=assembly"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:MessagePopup/>
    ///
    /// </summary>
    public class MessagePopup : UserControl
    {
        public static readonly DependencyProperty BusinessTypeProperty =
         DependencyProperty.Register(nameof(BusinessType), typeof(string), typeof(MessagePopup), new PropertyMetadata(string.Empty));
        /// <summary>
        /// 业务类型
        /// </summary>
        public string BusinessType
        {
            get { return (string)GetValue(BusinessTypeProperty); }
            set { SetValue(BusinessTypeProperty, value); }
        }

        public static readonly DependencyProperty SecondsProperty =
            DependencyProperty.Register(nameof(Seconds), typeof(string), typeof(MessagePopup), new PropertyMetadata(string.Empty));
        /// <summary>
        /// 秒数
        /// </summary>
        public string Seconds
        {
            get { return (string)GetValue(SecondsProperty); }
            set { SetValue(SecondsProperty, value); }
        }

        static MessagePopup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MessagePopup), new FrameworkPropertyMetadata(typeof(MessagePopup)));
        }
    }
}

自定义控件样式

下面的样式使用 ControlTemplate 自定义的控件样式,其中的 Button 按钮是不能进行事件绑定的,当然命令绑定也是不行的。

<Application
    x:Class="assembly.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:assembly"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <!--#region-->
            <Style x:Key="popup" TargetType="{x:Type local:MessagePopup}">
                <Setter Property="Height" Value="436" />
                <Setter Property="Width" Value="840" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:MessagePopup}">
                            <Grid>
                                <Grid.Background>
                                    <ImageBrush ImageSource="pack://application:,,,/images/bg-Tips.png" />
                                </Grid.Background>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="0.7*" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                                <Grid Grid.Row="0" Margin="55,0">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="0.5*" />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <Button
                                        Width="100"
                                        Height="40"
                                        Margin="0,20,0,0"
                                        HorizontalAlignment="Right"
                                        Tag="0">
                                        <Button.Template>
                                            <ControlTemplate>
                                                <StackPanel VerticalAlignment="Center" Orientation="Horizontal">
                                                    <Image Source="pack://application:,,,/images/ico-close.png" />
                                                    <TextBlock
                                                        Margin="5,0,0,0"
                                                        VerticalAlignment="Center"
                                                        FontSize="28"
                                                        FontWeight="Black"
                                                        Foreground="#7582CC"
                                                        Text="关闭" />
                                                </StackPanel>
                                            </ControlTemplate>
                                        </Button.Template>
                                    </Button>
                                    <StackPanel
                                        Grid.Row="1"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Orientation="Horizontal">
                                        <TextBlock
                                            FontSize="42"
                                            FontWeight="Black"
                                            Text="" />
                                        <TextBlock
                                            FontSize="42"
                                            FontWeight="Black"
                                            Foreground="#F95A00"
                                            Text="{TemplateBinding BusinessType}" />
                                        <TextBlock
                                            FontSize="42"
                                            FontWeight="Black"
                                            Text="" />
                                    </StackPanel>
                                </Grid>
                                <Line
                                    Grid.Row="1"
                                    Margin="80,0"
                                    Stroke="#8DB2BD"
                                    StrokeDashArray="2,2"
                                    StrokeThickness="4"
                                    X1="0"
                                    X2="650" />
                                <Grid Grid.Row="2" Margin="55,0">
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0" Margin="75,0">
                                        <StackPanel
                                            Margin="0,30,0,0"
                                            VerticalAlignment="Center"
                                            Orientation="Horizontal">
                                            <TextBlock
                                                VerticalAlignment="Center"
                                                FontSize="32"
                                                Foreground="#002C86"
                                                Text="" />
                                            <Image
                                                Height="40"
                                                Margin="20,0"
                                                Source="pack://application:,,,/images/ico-arrow.png" />
                                            <Button
                                                Width="180"
                                                Height="50"
                                                Tag="1">
                                                <Button.Template>
                                                    <ControlTemplate>
                                                        <Border Background="#DDE2FF" CornerRadius="5">
                                                            <StackPanel
                                                                Height="40"
                                                                HorizontalAlignment="Center"
                                                                VerticalAlignment="Center"
                                                                Orientation="Horizontal">
                                                                <Image Source="pack://application:,,,/images/ico-filer.png" />
                                                                <TextBlock
                                                                    Margin="5,0,0,0"
                                                                    VerticalAlignment="Center"
                                                                    FontSize="28"
                                                                    FontWeight="Black"
                                                                    Foreground="#7582CC"
                                                                    Text="跳转页面" />
                                                            </StackPanel>
                                                        </Border>
                                                    </ControlTemplate>
                                                </Button.Template>
                                            </Button>
                                        </StackPanel>
                                    </Grid>
                                    <Grid Grid.Row="1">
                                        <StackPanel
                                            Margin="0,20,0,0"
                                            HorizontalAlignment="Center"
                                            VerticalAlignment="Center"
                                            Orientation="Horizontal">
                                            <TextBlock
                                                FontSize="38"
                                                Foreground="#FFD873"
                                                Text="{TemplateBinding Seconds}" />
                                            <TextBlock
                                                FontSize="38"
                                                Foreground="#FFD873"
                                                Text="" />
                                            <TextBlock
                                                Margin="10,0,0,0"
                                                VerticalAlignment="Bottom"
                                                FontSize="32"
                                                Foreground="#FFFFFF"
                                                Text="" />
                                        </StackPanel>
                                    </Grid>
                                </Grid>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <!--#endregion-->
        </ResourceDictionary>
    </Application.Resources>
</Application>

效果

注册使用附加事件

使用该自定义控件时,为其注册 Button.Click 事件,属于原生路由事件。对应其用方法可以得出,该事件触发的是 Button 元素的 Click 事件。

简单来说就是,只有自定义控件中的 Button 元素才能触发当前的 Click 事件。(附加事件用法)

<Window
    x:Class="assembly.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:comm="clr-namespace:assembly"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="900"
    Height="550"
    WindowStartupLocation="CenterScreen"
    mc:Ignorable="d">
    <Grid>
        <comm:MessagePopup
            x:Name="popup"
            Width="840"
            Height="436"
            Button.Click="popup_Click"
            Style="{StaticResource popup}"
            Visibility="Visible" />
    </Grid>
</Window>

元素树中声明了两个 Buuton 这里暂且通过 Button 的 Tag 值来区分,不仅限于 Tag。

private void popup_Click(object sender, RoutedEventArgs e)
{
    string tag = (string)((FrameworkElement)e.OriginalSource).Tag;
    if (tag == "0")
    {
        MessageBox.Show("是关闭按钮");
        //CloseTimer();
    }
    else if (tag == "1")
    {
        MessageBox.Show("是跳转按钮");
    }
}

效果

到此这篇关于一文带你了解WPF中的附加事件的文章就介绍到这了,更多相关WPF附加事件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • WPF自定义路由事件

    与依赖项属性类似,WPF也为路由事件提供了WPF事件系统这一组成.为一个类型添加一个路由事件的方式与为类型添加依赖项属性的方法类似,添加一个自定义路由事件的步骤: 一.声明路由事件变量并注册 定义只读的静态变量字段RouteEvent类来声明一个变量,然后使用EventManager的RegisterRoutedEvent()方法向事件系统注册路由事件,该方法的签名如下: public static RoutedEvent RegisterRoutedEvent(string name, Rou

  • 解决WPF附加属性的Set函数不调用的问题

    今天写程序的时候用到了附加属性,我是用VS内置的propa的代码段来实现的,代码如下: class Attach { public static bool GetIsEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsEnabledProperty); } public static void SetIsEnabled(DependencyObject obj, bool value) { obj.SetValue(IsEnab

  • WPF路由事件之逻辑树和可视树遍历

    一.什么是逻辑树 逻辑树就是描述WPF界面元素的实际构成,它是由程序在XAML中所有的UI元素组成.最显著的特点就是由布局控件.或者其他常用的控件组成. <Window x:Class="WpfRouteEvent.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/win

  • c# wpf如何附加依赖项属性

    附加依赖项属性是一个属性本来不属于对象自己,但是某些特定场景其他的对象要使用该对象在这种场景下的值.这个值只在这个场景下使用.基于这个需求设计出来的属性.这里主要涉及到一个解耦问题.最大的优势是在特定场景下使用的属性,可以在特定场景下定义.这样业务上不会导致代码全部混在某个模块里.提升代码可维护性. 我们举例一段代码.假设有个类Person.包含了身份ID(IdentityID),姓名(Name),出生年月(Birth date),性别(gender),民族(Nation). 有一个School

  • WPF路由事件中的三种策略介绍

    什么是路由事件 路由事件是具有更强传播能力的事件,它可以在元素树中向上冒泡和向下隧道传播,并且能够沿着传播路径被事件处理程序来处理. 路由事件允许事件在某个元素上被处理,即使这个事件源自于另外一个元素.事件路由允许某个元素的事件由另外一个元素引发. 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而

  • 一文带你理解 Vue 中的生命周期

    目录 1.beforeCreate & created 2.beforeMount & mounted 3.beforeUpdate & updated 4.beforeDestroy & destroyed 5.activated & deactivated 前言: 每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如需要设置数据监听.编译模板.挂载实例到 DOM.在数据变化时更新 DOM 等.同时在这个过程中也会运行一些叫做生命周期钩子的函数,给予用户

  • 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用

    目录 函数式接口概述 函数式接口示例 1.Runnable接口 2.自定义函数式接口 3.作为参数传递 Lambda 表达式 内置函数式接口 Lambda简述 Lambda语法 方法引用 构造器引用 数组引用 函数式接口概述 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象. 可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口.同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

  • 一文带你了解Java中的ForkJoin

    目录 什么是ForkJoin? ForkJoinTask 任务 ForkJoinPool 线程池 工作窃取算法 构造方法 提交方法 创建工人(线程) 例:ForkJoinTask实现归并排序 ForkJoin计算流程 前言: ForkJoin是在Java7中新加入的特性,大家可能对其比较陌生,但是Java8中Stream的并行流parallelStream就是依赖于ForkJoin.在ForkJoin体系中最为关键的就是ForkJoinTask和ForkJoinPool,ForkJoin就是利用

  • 一文带你了解Java中的Object类及类中方法

    目录 1. Object类介绍 2. 重写toString方法打印对象 3. 对象比较equals方法 4. hashCode方法 1. Object类介绍 Object是Java默认提供的一个类.Java里面除了Object类,所有的类都是存在继承关系的.默认会继承Object父 类.即所有类的对象都可以使用Object的引用进行接收. 范例:使用Object接收所有类的对象 class Person{} class Student{} public class Test { public s

  • 一文带你了解Qt中槽的使用

    目录 一.建立槽和按钮之间的连接 二.槽函数的定义 一.建立槽和按钮之间的连接 connect(信号发送者,发送的信号,信号接收者,信号接收者的槽函数) 1.例子 connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(showinfo())); 解释: 信号反发送者:pushButton(这是一个按钮),发送信号:clicked(点击按钮),信号接收者:this(本类),信号接收者的槽函数:showinfo(点击按钮后响应的函数) 二.槽函

  • 一文带你了解Golang中interface的设计与实现

    目录 前言 接口是什么 iface 和 eface 结构体 _type 是什么 itab 是什么 生成的 itab 是怎么被使用的 itab 关键方法的实现 根据 interfacetype 和 _type 初始化 itab 接口断言过程总览(类型转换的关键) panicdottypeI 与 panicdottypeE iface 和 eface 里面的 data 是怎么来的 convT* 方法 Java 里面的小整数享元模式 总结 在上一篇文章<go interface 基本用法>中,我们了

  • 一文带你了解Vue3中toRef和toRefs的用法

    toRef 顾名思义,不是ref 响应式数据,给它转成ref 响应式数据 通俗易懂的理解: <template> <h3>姓名:{{ person.name }}</h3> <h3>年龄:{{ person.age }}</h3> <h3>薪资:{{ person.job.j1.salary }}</h3> <button @click="person.name += '!'">修改姓名&l

  • 一文带你了解Python中的双下方法

    目录 前言 1. init方法 2. 运算符的双下方法 2.1 比较运算符 2.2 算术运算符 2.3 反向算术运算符 2.4 增量赋值运算符 2.4 位运算符 3.字符串表示 4.数值转换 5.集合相关的双下方法 6.迭代相关的双下方法 7.类相关的双下方法 7.1 实例的创建和销毁 7.2 属性管理 7.3 属性描述符 8.总结 前言 大家在写 Python 代码的时候有没有这样的疑问. 为什么数学中的+号,在字符串运算中却变成拼接功能,如'ab' + 'cd'结果为abcd:而*号变成了重

  • 一文带你了解MySQL中触发器的操作

    目录 概述 介绍 触发器的特性 操作—创建触发器 操作—new和old 操作—查看触发器 操作—删除触发器 注意事项 概述 介绍 触发器,就是一种特殊的存储过程.触发器和存储过程一样是一个能够完成特定功能.存储在数据库服务器上的SQL片段,但是触发器无需调用,当对数据库表中的数据执行DML操作时自动触发这个SQL片段的执行,无需手动条用. 在MySQL中,只有执行insert,delete,update操作时才能触发触发器的执行 触发器的这种特性可以协助应用在数据库端确保数据的完整性,日志记录,

  • 一文带你了解Java中IO流与Guava的使用

    目录 Guava IO 分类 常用的流 示例 Guava中的IO 其他 结束语 Guava IO 日常系统交互中,文件的上传下载都是常见的,一般我们会通过jdk提供的IO操作库帮助我们实现.IO指的是数据相对当前操作程序的入与出,将数据通过 输出流从程序输出,或者通过输入流将数据(从文件.网络.数据等)写入到程序,这里的IO指的是基于流作为载体进行数据传输.如果把数据比作合理的水,河就是IO流,也是数据的载体. Java为我们提供了非常多的操作IO的接口与类,帮助开发者实现不同源间的数据传输,比

随机推荐