XAML的事件处理

Fri 19 July 2019 / In categories Library

WinRT, XAML

如果在XAML中绑定事件处理机制呢?

数据终究要回归到代码,这就是为什么在XAML中,每个页面都有Code-Behind(幕后代码)来支持。幕后代码其实是一个派生自Page类的子类,定义了很多跟XAML页面的交互。这些交互基本上有两种,一种是通过Name或者x:Name直接引用XAML元素,从而改变其属性,另一种,便是事件处理。

可以在幕后代码中通过重定义Page中的On开头的方法来进行事件处理,比如:

public sealed partial class MainPage : Page {
    ...
    protected override void OnTapped (TappedRoutedEventArgs args) {
        ...
    }
    ...
}

上面的代码重定义了Page的OnTapped方法,这样一来,页面上的所有Tap事件(也就是点击事件)都会传到Page的这个方法来处理。你可以在这个方法中通过args的OriginalSource属性来判断具体发生事件的对象,然后进行相应的处理。

如果你不想在页面级别处理事件,那么也可以在子元素级别处理事件,比如:

<TextBlock Text="Hello"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Tapped="OnTextBlockTapped" />

上面的XAML片段中的TextBlock定义了Tapped权属,值为OnTextBlockTapped,这样一来,该TextBlock上发生的点击事件就先由OnTextBlockTapped处理,而不是直接到Page级别处理。但是在TextBlock级别上处理玩完了之后,事件会向上蔓延,直到被Page的OnTapped捕获并处理为止。如果想避免事件蔓延,可以在OnTextBlockTapped处理完事件之后,将args的Handled权属置为true,就会停止其蔓延。

如果你需要在Page级别增加一个事件处理器,这个事件处理器不在乎事件的Handled是否为true,那么你需要通过AddHandler来添加一个自定义的事件处理器:

this.AddHandler(UIElement.TappedEvent,
	new TappedEventHandler(OnPageTapped),
	true);

和DependencyProperty一样,可以通过UIElement.TappedEvent这种类静态属性在全局引用一个事件类型。UIElement.TappedEvent顾名思义,指代的就是Tapped事件,并且是从RoutedEvent派生出来的。第二个参数new TappedEventHandler(OnPageTapped)创建了一个自定义的事件处理对象,其相应的事件处理器是OnPageTapped,第三个参数true表明即便事件的Handled为true,也要让此事件处理器知晓并处理此事件。

需要注意的是: UIElement.TappedEvent和DependencyProperty一样,也是全局可获取的

在事件触发过程中,有几个因素会影响事件的传播:

  • 有些XAML元素如果没有background的话,是不处理事件的,比如Gride
  • 元素的HorizontalAlignment和VerticalAlignment如果不设置的话,默认是stretch状态,占满所有可用的空间,会比肉眼看起占有的空间要大,会吸收所占空间内的所有事件,导致意外。

最后小结一下,Winrt中支持的事件类型并不多,只有:

  • 若干种Pointer开头的用于表示触控、鼠标、手写笔的事件
  • 若干种Manipulation开头的触摸板手势动作
  • 两种键盘事件
  • 若干种抽象事件,比如Tapped、DoubleTapped、RightTapped、Holding等等

(完)

Load Disqus Comments