欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

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

来源: 开发者 投稿于  被查看 35670 次 评论:197

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


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

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

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

 \\


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

\


 

好,下面让我们来结合程序详细介绍一下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事件。
  这是完成后的手机界面:

 \


 

接下来,我们添加后台的事件处理程序,上代码。
  首先添加一个名字空间:
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,我们发现输出窗口会打印一下文字:  

 \


 

我们首先观察前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控件中又包含了一行文本。
  这是添加完成后的手机界面。

 \


 

接下来是事件处理程序的代码。
 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,我们会看到输出窗口会发生变化。 

 \


 

 由于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。

 \


单击带有CheckBox控件的ListBoxItem   

\


 

我们发现当单击只有文本的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

相关文章

    暂无相关文章
相关频道:

用户评论