【WPF.NET开发】预览事件

这篇具有很好参考价值的文章主要介绍了【WPF.NET开发】预览事件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文内容

  1. 先决条件
  2. 预览标记为“已处理”的事件
  3. 通过控件解决事件禁止问题

预览事件,也称为隧道事件,是从应用程序根元素向下遍历元素树到引发事件的元素的路由事件。 引发事件的元素在事件数据中报告为Source
。 并非所有事件场景都支持或需要预览事件。 本文介绍了预览事件存在的位置以及应用程序或组件如何与其交互。

1、先决条件

本文假定你对路由事件有基本的了解,并且已阅读路由事件概述
。 若要遵循本文中的示例,如果熟悉 Extensible Application Markup Language (XAML) 并知道如何编写 Windows Presentation Foundation (WPF) 应用程序,将会很有帮助。

2、预览标记为“已处理”的事件

在事件数据中将预览事件标记为“已处理”时要谨慎。 将预览事件标记为已在引发该事件的元素之外的其他元素上处理,可阻止引发该事件的元素处理该事件。 有时,将预览事件标记为“已处理”是有意的。 例如,复合控件可能会禁止由单个组件引发的事件,并将它们替换为由完整控件引发的事件。 控件的自定义事件可以根据组件状态关系提供自定义的事件数据和触发器。

对于
输入事件,事件数据由每个事件的预览和非预览(浮升)等效项共享。 如果使用预览事件类处理程序将输入事件标记为“已处理”,则通常不会调用浮升输入事件的类处理程序。 或者,如果使用预览事件实例处理程序将事件标记为“已处理”,则通常不会调用浮升输入事件的实例处理程序。 尽管即使将事件标记为“已处理”,你也可以配置要调用的类和实例处理程序,但该处理程序配置并不常见。

并非所有预览事件都是隧道
事件。 例如,PreviewMouseLeftButtonDown 输入事件通过元素树跟踪向下路由,但它是由路径中的每个 UIElement 引发和重新引发的
直接路由事件。

3、通过控件解决事件禁止问题

一些复合控件在组件级别禁止输入事件,以便将其替换为自定义的高级事件。 例如,WPF ButtonBase 将 MouseLeftButtonDown 浮升输入事件标记为在其 OnMouseLeftButtonDown 方法中处理并引发 Click 事件。 MouseLeftButtonDown 事件及其事件数据仍沿元素树路径继续,但由于该事件在事件数据中标记为 Handled,因此将仅调用配置为响应“已处理”事件的处理程序。

如果希望由应用程序根目录的其他元素处理标记为“已处理”的路由事件,则可以执行以下操作:

  • 通过调用 UIElement.AddHandler(RoutedEvent, Delegate, Boolean) 方法并将参数 handledEventsToo 设置为 true 来附加处理程序。 此方法需要在获取要附加到的元素的对象引用后,在代码隐藏中附加事件处理程序。

  • 如果标记为“已处理”的事件是浮升事件,则附加等效预览事件的处理程序(如果可用)。 例如,如果控件禁止了 MouseLeftButtonDown 事件,则可以改为附加 PreviewMouseLeftButtonDown 事件的处理程序。 此方法仅适用于实现
    隧道和
    浮升路由策略并共享事件数据的基元素输入事件。

以下示例实现了一个名为 componentWrapper 的基本自定义控件,其中包含一个 TextBox。 控件被添加到名为 outerStackPanel 的 StackPanel。

<StackPanel Name="outerStackPanel"
    VerticalAlignment="Center"
    custom:ComponentWrapper.CustomKey="Handler_PrintEventInfo"
    TextBox.KeyDown="Handler_PrintEventInfo"
    TextBox.PreviewKeyDown="Handler_PrintEventInfo" >
    <custom:ComponentWrapper
        x:Name="componentWrapper"
        TextBox.KeyDown="ComponentWrapper_KeyDown"
        custom:ComponentWrapper.CustomKey="Handler_PrintEventInfo"
        HorizontalAlignment="Center">
        <TextBox Name="componentTextBox" Width="200" KeyDown="Handler_PrintEventInfo" />
    </custom:ComponentWrapper>
</StackPanel>

每当发生击键操作时,componentWrapper 控件都会侦听由其 TextBox 组件引发的 KeyDown 浮升事件。 在这种情况下,componentWrapper 控件:

  1. 将 KeyDown 浮升路由事件标记为“已处理”以禁止该事件。 因此,只会触发在代码隐藏中配置为响应“已处理”KeyDown 事件的 outerStackPanel 处理程序。 不会调用在 XAML 中为 KeyDown 事件附加的 outerStackPanel 处理程序。

  2. 引发名为 CustomKey 的自定义浮升路由事件,该事件触发 CustomKey 事件的 outerStackPanel 处理程序。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // Attach a handler on outerStackPanel that will be invoked by handled KeyDown events.
        outerStackPanel.AddHandler(KeyDownEvent, new RoutedEventHandler(Handler_PrintEventInfo), 
            handledEventsToo: true);
    }

    private void ComponentWrapper_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        Handler_PrintEventInfo(sender, e);

        Debug.WriteLine("KeyDown event marked as handled on componentWrapper.\r\n" +
            "CustomKey event raised on componentWrapper.");

        // Mark the event as handled.
        e.Handled = true;

        // Raise the custom click event.
        componentWrapper.RaiseCustomRoutedEvent();
    }

    private void Handler_PrintEventInfo(object sender, System.Windows.Input.KeyEventArgs e)
    {
        string senderName = ((FrameworkElement)sender).Name;
        string sourceName = ((FrameworkElement)e.Source).Name;
        string eventName = e.RoutedEvent.Name;
        string handledEventsToo = e.Handled ? " Parameter handledEventsToo set to true." : "";

        Debug.WriteLine($"Handler attached to {senderName} " +
            $"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}");
    }

    private void Handler_PrintEventInfo(object sender, RoutedEventArgs e)
    {
        string senderName = ((FrameworkElement)sender).Name;
        string sourceName = ((FrameworkElement)e.Source).Name;
        string eventName = e.RoutedEvent.Name;
        string handledEventsToo = e.Handled ? " Parameter handledEventsToo set to true." : "";

        Debug.WriteLine($"Handler attached to {senderName} " +
            $"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}");
    }

    // Debug output:
    //
    // Handler attached to outerStackPanel triggered by PreviewKeyDown event raised on componentTextBox.
    // Handler attached to componentTextBox triggered by KeyDown event raised on componentTextBox.
    // Handler attached to componentWrapper triggered by KeyDown event raised on componentTextBox.
    // KeyDown event marked as handled on componentWrapper.
    // CustomKey event raised on componentWrapper.
    // Handler attached to componentWrapper triggered by CustomKey event raised on componentWrapper.
    // Handler attached to outerStackPanel triggered by CustomKey event raised on componentWrapper.
    // Handler attached to outerStackPanel triggered by KeyDown event raised on componentTextBox. Parameter handledEventsToo set to true.
}

public class ComponentWrapper : StackPanel
{
    // Register a custom routed event using the Bubble routing strategy.
    public static readonly RoutedEvent CustomKeyEvent = 
        EventManager.RegisterRoutedEvent(
            name: "CustomKey",
            routingStrategy: RoutingStrategy.Bubble,
            handlerType: typeof(RoutedEventHandler),
            ownerType: typeof(ComponentWrapper));

    // Provide CLR accessors for assigning an event handler.
    public event RoutedEventHandler CustomKey
    {
        add { AddHandler(CustomKeyEvent, value); }
        remove { RemoveHandler(CustomKeyEvent, value); }
    }

    public void RaiseCustomRoutedEvent()
    {
        // Create a RoutedEventArgs instance.
        RoutedEventArgs routedEventArgs = new(routedEvent: CustomKeyEvent);

        // Raise the event, which will bubble up through the element tree.
        RaiseEvent(routedEventArgs);
    }
}

该示例演示了两种解决方法,用于获取禁止的 KeyDown 路由事件以调用附加到 outerStackPanel 的事件处理程序:

  • 将 PreviewKeyDown 事件处理程序附加到 outerStackPanel。 由于预览输入路由事件先于等效的浮升路由事件,因此示例中的 PreviewKeyDown 处理程序在 KeyDown 处理程序之前运行,后者通过共享事件数据禁止预览和浮升事件。

  • 使用代码隐藏中的 UIElement.AddHandler(RoutedEvent, Delegate, Boolean) 方法将 KeyDown 事件处理程序附加到 outerStackPanel,并将 handledEventsToo 参数设置为 true

 备注

将输入事件的预览或非预览等效项标记为“已处理”都是禁止控件组件引发的事件的策略。 使用的方法取决于应用程序要求。文章来源地址https://www.toymoban.com/news/detail-771828.html

到了这里,关于【WPF.NET开发】预览事件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【WPF.NET开发】WPF中的窗口

    目录 1、窗口类 2、实现窗口 2.1 为 MSBuild 配置窗口 3、窗口生存期 3.1 打开窗口 3.2 窗口激活 3.3 关闭窗口 3.4 窗口生存期事件 4、窗口位置 4.1 最顶层窗口和 z 顺序 5、窗口大小 6、大小调整属性的优先级顺序 7、窗口状态 8、窗口外观 8.1 重设大小模式 8.2 Window style 8.3 任务栏显示

    2024年02月04日
    浏览(42)
  • 【WPF.NET开发】WPF中的XAML资源

    使用 XAML 中的资源 静态和动态资源 静态资源 动态资源 样式、DataTemplate 和隐式键 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和访问资源。  备注

    2024年01月17日
    浏览(62)
  • 【WPF.NET开发】流文档

    什么是流文档? 流文档类型 创建流内容 与流相关的类 内容架构 自定义文本 流文档旨在优化查看和可读性。 流文档根据运行时变量(例如,窗口大小、设备分辨率和可选的用户首选项)来动态调整和重新排列内容,而不是设置为一个预定义的布局。 此外,流文档还提供一

    2024年01月17日
    浏览(39)
  • 【WPF.NET开发】OpenType字体

    OpenType 字体格式 变量 大写字母 连字 花体 备用项 数字样式 版式类 本主题概述了 Windows Presentation Foundation (WPF) 中 OpenType 字体技术的一些主要功能。 OpenType 字体格式是 TrueType® 字体格式的扩展,增加了对 PostScript 字体数据的支持。 OpenType 字体格式由 Microsoft 和 Adobe Corporatio

    2024年01月16日
    浏览(41)
  • VisualStudio[WPF/.NET]基于CommunityToolkit.Mvvm架构开发

    项目模板选择如下: 暂时随机填一个目标框架,待会改: 双击“解决方案资源管理器”中项目CU-APP, 打开项目工程文件CU-APP.csproj, 修改目标框架 TargetFramework 为.net framework 4.7.2 ;  C#语言版本 LangVersion 为  9.0  \\\"工具\\\" - \\\"NuGet包管理器\\\",“管理解决方案的NuGet程序包(N)”,  或者,

    2024年02月07日
    浏览(39)
  • .NET6: 开发基于WPF的摩登三维工业软件 (7)

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 做为一个摩登的工业软件,提供可编程的脚本能力是必不可少的能力。脚本既可以方便用户进行二次开发,也对方便对程序进行自动化测试。本文将结合

    2024年02月05日
    浏览(43)
  • 使用.net 6.0框架的WPF应用如何引用System.Windows.Forms这个dll

    在.net 6.0的WPF应用中,想使用OpenFileDialog 这个类或者FolderBrowserDialog这个类,是无法找到System.Windows.Forms这个dll引用的,即使从系统C盘里搜索到System.Windows.Forms.dll放到项目里,也会出现异常,而无法识别WPF自带的一些初始化方法。 OpenFileDialog还好,因为他有两个命名空间都有它

    2024年02月12日
    浏览(34)
  • .net wpf程序 移花接木

    最近在研究C# .net桌面程序。非常有趣 软件是国外作者写的 公司要求修改翻译 从最初的开源变成闭源再到加壳. 一路让我这个小小的职员好蛋疼. 软件是VS2015 C# WPF 程序 在不脱壳的情况下 实现挂钩类托管函数 遍历WPF控件汉化 首先通过各种手段脱壳目标程序,哪怕是不能运行

    2024年02月07日
    浏览(36)
  • WPF .NET 7.0学习整理(一)

    参照文档进行不系统的整理,看到那写到那O.o DependencyProperty:使用专有字段支持属性的标准模式的替代方法。 DependencyObject:定义了可以注册和拥有依赖属性的基类。 属性及其支持性 DependencyProperty 字段的命名约定非常重要。 字段总是与属性同名,但其后面追加了 Property 后

    2024年02月09日
    浏览(34)
  • WPF C# .NET7 基础学习

    学习视频地址:https://www.bilibili.com/video/BV1hx4y1G7C6?p=3vd_source=986db470823ebc16fe0b3d235addf050 开发工具:Visual Studio 2022 Community 基础框架:.Net 6.0 下载创建过程略 .Net和.Framework 区别是Net是依赖项,Framework是引用 1.定义一个命名空间, 最常用 不只包括using namespace,还用开头使用的usin

    2024年02月10日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包