2 xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
3 xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml "
4 Title = " WinMain " Height = " 494 " Width = " 715 " >
5 < Grid >
6 < Grid.ColumnDefinitions >
7 < ColumnDefinition Width = " 371* " />
8 < ColumnDefinition Width = " 344* " />
9 </ Grid.ColumnDefinitions >
10 < Menu Height = " 25 " Name = " menu1 " VerticalAlignment = " Top " Grid.ColumnSpan = " 2 " >
11 < MenuItem Header = " 第一级菜单 " Click = " MenuItem_Click " >
12 < MenuItem Header = " 第二级菜单1 " />
13 < MenuItem Header = " 第二级菜单2 " />
14 </ MenuItem >
15 </ Menu >
16 </ Grid >
17 </ Window >
18
19
20 /// <summary>
21 /// WinMain.xaml 的交互逻辑
22 /// </summary>
23 public partial class WinMain : Window
24 {
25 public WinMain()
26 {
27 InitializeComponent();
28 }
29
30 private void MenuItem_Click( object sender, RoutedEventArgs e)
31 {
32 object obj = e.Source;
33 bool handled = e.Handled;
34
35 RoutedEvent routedEvent = e.RoutedEvent;
36 RoutingStrategy routingStrategy = routedEvent.RoutingStrategy;
37
38
39 MessageBox.Show( " 触发了事件 \r\n 源: " + e.Source.ToString());
40 }
41
42 }
我们重点看节点Menu和MenuItem,menu是菜单的根节点。header属性是菜单的标题。(顺便说一句,在winform里这些都是设置属性"Text"的,而在wpf里,大多变成"Content"属性)。而让人惊讶的是 “在代码设计器中,我们只能对一级菜单注册事件”,查看代码第11行里。有句“Click="MenuItem_Click"” 熟悉 html人都能明白这个意思,就是注册一个事件,事件名字是“MenuItem_Click”,而事件的实现代码当然是在"CodeBehind"代码后置文件里找了。这里 “二级菜单1”和“二级菜单2”两个菜单的单击都会触发"MenuItem_Click"。也就是说“子控件里的单击 触发了 父控件里注册的事件”。其实是个 “事件路由(RoutedEvent)”,流程如下:
1.先触发子控件的click事件,(本示例没有订阅该事件,等下我们做个订阅尝试)。
2.再触发父控件的click事件。
3.依次再触发该控件的上一级父控件的事件。
这里就有了事件 触发策略问题。即事件如何传递。
我们看下 注册事件的代码 private void MenuItem_Click(object sender, RoutedEventArgs e) ,方法签名里和我们常见的方法签名区别是这个这个参数RoutedEventArgs ,该参数属性有(摘自msdn):
名称 | 说明 | |
---|---|---|
Handled | 获取或设置一个值,该值指示路由事件在路由过程中的事件处理当前状态。 | |
OriginalSource | 在父类进行任何可能的 Source 调整之前,获取原始报告源(由纯粹命中测试确定)。 | |
RoutedEvent | 获取或设置与此 RoutedEventArgs 实例关联的 RoutedEvent。 | |
Source | 获取或设置对引发事件的对象的引用。 |
我们在事件中,如果想终止该事件的继续传递,设置e.Handled= true就可以了。
事件使用的委托的方法签名如下:
public delegate void RoutedEventHandler( sender, RoutedEventArgs e )
实际上一切都是由RoutedEvent 对象来管理的。也就是说。RoutedEvent处理了事件的传递方式。
名称 | 说明 | |
---|---|---|
HandlerType | 获取路由事件的处理程序类型。 | |
Name | 获取路由事件的标识名称。 | |
OwnerType | 获取路由事件的已注册所有者类型。 | |
RoutingStrategy | 获取路由事件的路由策略。 |
public enum RoutingStrategy 路由策略的枚举类型如下:
成员名称 | 说明 | |
---|---|---|
Tunnel | 路由事件使用隧道策略,以便事件实例通过树向下路由(从根到源元素)。 | |
Bubble | 路由事件使用冒泡策略,以便事件实例通过树向上路由(从事件元素到根)。 | |
Direct | 路由事件不通过元素树路由,但支持其他路由事件功能,例如类处理、 或 。 |
我们可以设置我们RoutedEvent的传递方式,当然这要自己写控件的时候才用得到。
稍候待续...