欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Windows Phone中的路由事件-以ListBox控件为例

程序员文章站 2022-03-05 15:52:09
今天我们来介绍一下Windows Phone中的路由事件,以ListBox控件为例。   首先我们来熟悉一下路由事件的概念。   路由事件是具有更强传播能力的事件,他们可以在元...

今天我们来介绍一下Windows Phone中的路由事件,以ListBox控件为例。

  首先我们来熟悉一下路由事件的概念。

  路由事件是具有更强传播能力的事件,他们可以在元素树中向上冒泡和向下隧道传播,并且沿着传播路径被事件处理程序处理。路由事件经常以冒泡路由事件和隧道路由事件的形式出现,冒泡路由事件是在元素树中向上传播的一种事件,触发事件的源会把事件传递给他的父元素,他的父元素又会将事件继续向上传递,直到传递到元素树的顶端,或者有着特殊的逻辑处理。稍后会给大家详细讲述冒泡路由事件的工作方式。隧道路由事件的工作方式和冒泡路由事件相同,但方向相反。他是在元素树中向下传播的一种事件,触发事件的源的会寻找他的子元素,然后把事件传递给他。隧道路由事件通常比较容易辨认,因为他们都以单词Preview开头。隧道路由事件总是在冒泡路由事件之前被触发。今天我们的重点是冒泡路由事件。

 Windows Phone中的路由事件-以ListBox控件为例Windows Phone中的路由事件-以ListBox控件为例


由于是讲Windows phone中的路由事件,那就要讲一下触摸屏设备所特有的事件--触摸事件。在Windows phone中 触摸事件主要有3种,比较简单,分别是ManipulationStarted事件,他是在用户的手指触摸到屏幕时触发的事件。ManipulationDelta事件,他是用户的手指在屏幕上滑动式触发的事件。ManipulationCompleted事件,他是用户的手指离开屏幕时触发的事件。值得注意的是,以上三种触摸事件都是冒泡路由事件。

Windows Phone中的路由事件-以ListBox控件为例


 

好,下面让我们来结合程序详细介绍一下Windows phone中的路由事件。
  新建一个Windows Phone应用程序,在内容Grid中添加以下XAML代码。
 
 1 <ListBox  x:Name="listBox"
 2                       ManipulationStarted="listBox_ManipulationStarted"
 3                       ManipulationCompleted="listBox_ManipulationCompleted"
 4                       >
 5                 <ListBoxItem x:Name="listBoxItem1"
 6                     ManipulationStarted="listBoxItem1_ManipulationStarted" 
 7                     ManipulationCompleted="listBoxItem1_ManipulationCompleted">
 8                     <TextBlock x:Name="textBlock1" FontSize="30"
 9                                    Text="文本一文本一文本一"
10                                    ManipulationStarted="textBlock1_ManipulationStarted"
11                                    ManipulationCompleted ="textBlock1_ManipulationCompleted"/>
12                 </ListBoxItem>
13                 <ListBoxItem x:Name="listBoxItem2"
14                     ManipulationStarted="listBoxItem2_ManipulationStarted" 
15                     ManipulationCompleted="listBoxItem2_ManipulationCompleted">
16                     <TextBlock x:Name="textBlock2" FontSize="30"
17                                    Text="文本二文本二文本二"
18                                    ManipulationStarted="textBlock2_ManipulationStarted"
19                                    ManipulationCompleted="textBlock2_ManipulationCompleted"/>
20                 </ListBoxItem>
21             </ListBox>
 
  这段代码比较简单,包括一个listbox控件,和两个listboxitem,每个listboxitem的内容也比较简单,就是一行文本,我们给每个控件都分别注册了ManipulationStarted事件和ManipulationCompleted事件。
  这是完成后的手机界面:

 Windows Phone中的路由事件-以ListBox控件为例


 

接下来,我们添加后台的事件处理程序,上代码。
  首先添加一个名字空间:
1 using System.Diagnostics;
  然后是事件处理程序的代码:
 1 private void listBox_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
 2         {
 3             Debug.WriteLine("OUT PUT: listBox_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
 4         }
 5
 6         private void listBox_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
 7         {
 8             Debug.WriteLine("OUT PUT: listBox_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
 9         }
10
11         private void listBoxItem1_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
12         {
13             Debug.WriteLine("OUT PUT: listBoxItem1_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
14         }
15
16         private void listBoxItem1_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
17         {
18             Debug.WriteLine("OUT PUT: listBoxItem1_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
19         }
20
21         private void textBlock1_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
22         {
23             Debug.WriteLine("OUT PUT: textBlock1_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
24         }
25
26         private void textBlock1_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
27         {
28             Debug.WriteLine("OUT PUT: textBlock1_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
29         }
30
31         private void listBoxItem2_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
32         {
33             Debug.WriteLine("OUT PUT: listBoxItem2_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
34         }
35
36         private void listBoxItem2_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
37         {
38             Debug.WriteLine("OUT PUT: listBoxItem2_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
39         }
40
41         private void textBlock2_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
42         {
43             Debug.WriteLine("OUT PUT: textBlock2_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
44         }
45
46         private void textBlock2_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
47         {
48             Debug.WriteLine("OUT PUT: textBlock2_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
49         }
  每个事件处理程序都是类似的,他的功能是在调试时的输出窗口里打印一行文本,这样我们就可以清晰的看到每个事件处理的顺序。 www..2cto.com
  运行程序,并单击第一个ListBoxItem,我们发现输出窗口会打印一下文字:  

 Windows Phone中的路由事件-以ListBox控件为例


 

我们首先观察前3行文字,他是一个完整的冒泡路由过程,从触发事件的TextBlock,再到ListBoxItem,最后到元素树的*元素ListBox终止(其实ListBox并不是真正的*元素,真正的*元素应该是phone:PhoneApplicationPage控件,但由于没有对phone:PhoneApplicationPage控件的触摸事件进行处理,所以在这里是无法显示的,目前我们姑且认为ListBox控件就是元素树的*元素)。我们再来看最后一行文字,比较奇怪,ManipulationCompleted事件并没有完成一个完整的冒泡路由过程,这是怎么回事呢?我们在此留下一个悬念,稍后会给大家解释。
  我们继续完善代码。
  首先在ListBox中添加一个ListBoxItem。
 1 <ListBoxItem x:Name="listBoxItem3"
 2                              ManipulationStarted="listBoxItem3_ManipulationStarted"
 3                              ManipulationCompleted="listBoxItem3_ManipulationCompleted">
 4                     <CheckBox x:Name="checkBox"
 5                              ManipulationStarted="checkBox_ManipulationStarted"
 6                              ManipulationCompleted="checkBox_ManipulationCompleted"
 7                              >
 8                         <TextBlock x:Name="textBlock3" Text="文本三文本三文本三文本三文本三"
 9                                    ManipulationStarted="textBlock3_ManipulationStarted"
10                                    ManipulationCompleted="textBlock3_ManipulationCompleted"/>
11                     </CheckBox>
12                 </ListBoxItem>
  这个ListBoxItem的内容是一个CheckBox控件,CheckBox控件中又包含了一行文本。
  这是添加完成后的手机界面。

 Windows Phone中的路由事件-以ListBox控件为例


 

接下来是事件处理程序的代码。
 1  private void listBoxItem3_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
 2         {
 3             Debug.WriteLine("OUT PUT: listBoxItem3_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
 4         }
 5
 6         private void listBoxItem3_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
 7         {
 8             Debug.WriteLine("OUT PUT: listBoxItem3_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
 9         }
10
11         private void checkBox_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
12         {
13             Debug.WriteLine("OUT PUT: checkBox_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
14         }
15
16         private void checkBox_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
17         {
18             Debug.WriteLine("OUT PUT: checkBox_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
19         }
20
21         private void textBlock3_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
22         {
23             Debug.WriteLine("OUT PUT: textBlock3_ManipulationStarted in {0}", DateTime.Now.ToLongTimeString());
24         }
25
26         private void textBlock3_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
27         {
28             Debug.WriteLine("OUT PUT: textBlock3_ManipulationCompleted in {0}", DateTime.Now.ToLongTimeString());
29            
30         }
  和以前也是一样的,也是在调试时的输出窗口里打印一行文本。
  运行程序,并单击新添加的带有CheckBox的ListBoxItem,我们会看到输出窗口会发生变化。 

 Windows Phone中的路由事件-以ListBox控件为例


 

 由于ListBoxItem中包含了一个带有文本的CheckBox控件,所以元素树的层次增加了一层。我们可以清晰的看到,和上一次不一样的是,不论是ManipulationStarted事件还是ManipulationCompleted事件都完成了完整的冒泡路由传递,这又是为什么呢?

  为了进一步解释这个问题,我们进一步完善代码。

  首先给ListBox控件注册一个SelectionChanged事件。

1 <ListBox  x:Name="listBox"
2                       ManipulationStarted="listBox_ManipulationStarted"
3                       ManipulationCompleted="listBox_ManipulationCompleted"
4                       SelectionChanged="listBox_SelectionChanged"
5                      >  然后给SelectionChanged事件添加事件处理程序。

1 private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
2         {
3             Debug.WriteLine("OUT PUT: listBox_SelectionChanged in {0}", DateTime.Now.ToLongTimeString());
4         }  该事件处理程序功能和原来是类似的。

  运行程序,先后点击只有文本的ListBoxItem和带有CheckBox控件的ListBoxItem,我们注意对比两者的不同。

  点击只有文本的ListBoxItem。

 Windows Phone中的路由事件-以ListBox控件为例


单击带有CheckBox控件的ListBoxItem   

Windows Phone中的路由事件-以ListBox控件为例


 

我们发现当单击只有文本的ListBoxItem的时候,在TextBlock控件的ManipulationCompleted事件后,触发了ListBox的SelectionChanged事件,而单击带有CheckBox控件的ListBoxItem的时候并没有触发ListBox的SelectionChanged事件,事实上这就是问题的关键所在。  

  当ListBoxItem中包含着对单击或触摸有特殊处理的控件(Button、CheckBox、RatioButton)的时候,不会触发ListBox的SelectionChanged事件,会将事件继续向上传递。而ListBoxItem中仅仅有自身对单击或触摸没有特殊处理的控件(TextBlock Image),就会触发ListBox的SelectionChanged事件,而SelectionChanged就不会向上继续传递了。因为已经到了*元素ListBox那里。这就是冒泡路由事件的向上传递被中断的原因。  

  好了,到现在大家对应该windows phone中的路由事件应该已经有了一个大致的了解,希望大家能自己建立一个示例程序,试验一下其他控件在ListBox中的表现,这样能够更加深刻的理解路由事件。

 

摘自  DannyLittle