惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
J
Java Code Geeks
博客园_首页
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
P
Palo Alto Networks Blog
V
Vulnerabilities – Threatpost
雷峰网
雷峰网
O
OpenAI News
SecWiki News
SecWiki News
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
N
News | PayPal Newsroom
Project Zero
Project Zero
Forbes - Security
Forbes - Security
IT之家
IT之家
A
Arctic Wolf
WordPress大学
WordPress大学
Jina AI
Jina AI
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
Attack and Defense Labs
Attack and Defense Labs
博客园 - 聂微东
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
Cloudbric
Cloudbric
G
GRAHAM CLULEY
博客园 - 叶小钗
H
Hacker News: Front Page
腾讯CDC
量子位
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
C
Cyber Attacks, Cyber Crime and Cyber Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recorded Future
Recorded Future
C
CERT Recently Published Vulnerability Notes

博客园 - 赖仪灵

分享几个简单的WPF控件(代码) 捕捉WPF应用程序中XAML代码解析异常 设置WPF窗口相对于非WPF窗口的位置 上海.NET俱乐部--微软社区巡展VSTS上海专题活动 WPF关于WindowInteropHelper的一个BUG WPF全景体验 最优化WPF 3D性能(基于“Tier-2”硬件) Windows Vista桌面窗口管理器(3) 闲话WPF之二六(WPF性能优化点) 闲话WPF之二五(WPF中的ControlTemplate [3]) 闲话WPF之二四(WPF中的ControlTemplate [2]) Windows Vista桌面窗口管理器(2) 闲话WPF之二三(WPF中的ControlTemplate [1]) 闲话WPF之二二(WPF中的Style) Windows Vista桌面窗口管理器(1) 闲话WPF之二一(WPF中的数据处理 [3]) 闲话WPF之二十(WPF中的传递事件 [2] ) 闲话WPF之十八(WPF中的资源 [4] ) 闲话WPF之十七(WPF中的资源 [3])
闲话WPF之十九(WPF中的传递事件 [1] )
赖仪灵 · 2007-01-03 · via 博客园 - 赖仪灵

【传递事件】

WPF在.NET简单事件通知之上添加了很多基础结构。传递事件的设计使得事件可以与元素树一起很好的工作。事件发生后,可以在视觉树和逻辑树自动地进行上下传递,我们不需要添加任何额外的代码。

传递事件使得我们不需要过多关注于视觉树,这样封装对于我们理解WPF的元素合成非常重要。比如,我们点击一个按钮的事件,在点击的时候我们实际上点击的是一个ButtonChrome或者TextBlock,也就是说我们点击的是Button的内容元素。正是因为事件可以沿视觉树传递,Button才发现这个事件,并且可以处理。因此,我们可以给Button的Content当中添加任意的元素,而不会对事件有任何的影响。如果没有这样的事件传递,我们点击Button内的元素时,必须手动编写代码触发Button点击事件。

传递事件的的实现和行为与Dependency属性类似。同样,我们看看如何实现简单的传递事件。多数时候,传递事件并不比普通的.NET事件难。与Dependency属性一样,.NET语言(除了XAML)本身并不明白传递目标。这些支持都是基于WPF API。

public class Button
{
   // 传递的事件
   public static readonly RoutedEvent ClickEvent;

   static Button()
   {
      // 注册事件
      Button.DoubleClickEvent = EventManager.RegisterRoutedEvent(“Click”,
         RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Button));
      …
   }
 
   // .NET事件保证 (可选的)
   public event RoutedEventHandler Click
   {
      add { AddHandler(Button.ClickEvent, value); }
      remove { RemoveHandler(Button.ClickEvent, value); }
   }

   protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
   {
      …
      // 激发事件
      RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
      …
   }
    …
}

从上面的实现可以看出,事件与Dependency属性有很多相似之处。也是定义一个静态的RoutedEvent成员,同样在静态构造函数里注册事件。为了方便,也包装了一个普通的.NET事件。这里的AddHandler/RemoveHandler不是从DependencyObject派生,而是更高一级的基类System.Windows.UIElement。这两个方法为相应的事件添加/删除一个委派。在OnMouseLeftButtonDown中,我们构造一个事件参数,传入事件源对象this,然后调用RaiseEvent函数。

【事件策略和处理函数】

注册WPF事件时,我们需要为传递事件选择一种策略,这个策略指定了事件在元素树中传递的方式。WPF支持这样三种策略:

   Tunneling:事件首先在根元素激发,然后到达树下的每个元素直到源元素(或者有处理函数处理这个事件终止了传递)。

   Bubbling:事件首先在源元素激发,然后向上直到根元素(或者有处理函数处理这个事件终止了传递。

   Direct:事件只在源元素激发。这与普通的.NET事件一样,除了参与事件触发器。

在上面的例子中,我们注册的事件策略就是Bubbling。

传递事件的处理函数的参数与普通.NET事件一样。第一个参数System.Object表示处理函数依附的元素。第二个的System.EventArgs派生类,提供了如下四个有用的属性:

   Source:逻辑树中激发事件的原始元素。

   OriginalSource:视觉树中激发事件的原始元素。

   Handled:布尔值,表示事件是否被处理。

   RoutedEvent:实际的传递事件对象(比如Button.ClickEvent)。这个对于相同的处理函数处理多个传递事件时非常有用,可以用来区别传递事件。

Source和OriginalSource代表了逻辑树和视觉树对象。这有利于我们进行一些低级控制,但是对于有的事件,不需要区别它们,这两个的值是相同的。