Silverlight中的事件处理与鼠标操作详解
立即解锁
发布时间: 2025-08-26 01:35:04 阅读量: 13 订阅数: 41 AIGC 


Silverlight 4 in VB: 创建跨平台浏览器应用
# Silverlight中的事件处理与鼠标操作详解
## 1. 已处理(抑制)的事件
在Silverlight应用程序里,当控件接收到鼠标事件时,部分控件会对事件进行特殊处理。例如,当图4 - 3中的按钮接收到 `MouseLeftButtonDown` 事件时,它会将该事件标记为已处理。这样做能够阻止事件在控件层次结构中继续向上冒泡。大多数Silverlight控件运用这种处理技术来抑制 `MouseLeftButtonDown` 和 `MouseLeftButtonUp` 事件,从而用更实用的高级事件(如 `Click` 事件)来替代它们。
不过,存在一些元素不会处理 `MouseLeftButtonDown` 和 `MouseLeftButtonUp` 事件,具体如下:
- **用于显示位图的 `Image` 类**
- **用于显示文本的 `TextBlock` 类**
- **用于显示视频的 `MediaElement` 类**
- **用于二维绘图的形状类(`Line`、`Rectangle`、`Ellipse`、`Polygon`、`Polyline`、`Path`)**
- **用于排列元素的布局容器(`Canvas`、`StackPanel` 和 `Grid`)以及 `Border` 类**
这些例外情况使得我们能够在诸如 `Button` 这样的内容控件中无限制地使用这些元素。例如,若在按钮中放置一个 `TextBlock`,当点击该 `TextBlock` 时,`MouseLeftButtonUp` 事件会冒泡到按钮,进而触发按钮的 `Click` 事件。但要是将不在上述列表中的控件(如列表框、复选框或另一个按钮)放置在按钮内部,就会出现不同的行为。当点击嵌套元素时,`MouseLeftButtonUp` 事件不会冒泡到包含它的按钮,按钮也就不会记录点击操作。
需要注意的是,`MouseLeftButtonDown` 和 `MouseLeftButtonUp` 是控件会抑制的仅有的事件,而冒泡的按键事件(`KeyUp`、`KeyDown`、`LostFocus` 和 `GotFocus`)不会被任何控件抑制。
## 2. 事件冒泡示例
为了更好地理解事件冒泡和已处理事件,我们可以创建一个简单的示例,就像图4 - 4所示的那样。在这个示例中,`MouseLeftButtonDown` 事件从 `TextBlock` 或 `Image` 开始,在元素层次结构中传播。
通过为多个元素附加事件处理程序,我们可以观察 `MouseLeftButtonDown` 事件的冒泡过程。当事件在不同层次被拦截时,事件序列会显示在列表框中。图4 - 4展示了点击按钮中的笑脸图像后立即显示的情况。可以看到,`MouseLeftButtonDown` 事件先在图像中触发,接着在包含它的 `StackPanel` 中触发,最后被按钮拦截并处理。按钮不会触发 `MouseLeftButtonDown` 事件,因此该事件不会冒泡到包含按钮的 `Grid`。
以下是创建此测试页面的XAML代码:
```xml
<UserControl x:Class="RoutedEvents.EventBubbling"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Margin="3" MouseLeftButtonDown="SomethingClicked">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Button Margin="5" Grid.Row="0" MouseLeftButtonDown="SomethingClicked">
<StackPanel MouseLeftButtonDown="SomethingClicked">
<TextBlock Margin="3" MouseLeftButtonDown="SomethingClicked"
HorizontalAlignment="Center" Text="Image and text label"></TextBlock>
<Image Source="happyface.jpg" Stretch="None"
MouseLeftButtonDown="SomethingClicked"></Image>
<TextBlock Margin="3" HorizontalAlignment="Center"
MouseLeftButtonDown="SomethingClicked"
Text="Courtesy of the StackPanel"></TextBlock>
</StackPanel>
</Button>
<ListBox Grid.Row="1" Margin="5" x:Name="lstMessages"></ListBox>
<Button Grid.Row="3" Margin="5" Padding="3" x:Name="cmdClear"
Click="cmdClear_Click" Content="Clear List"></Button>
</Grid>
</UserControl>
```
`SomethingClicked()` 方法会简单地检查 `RoutedEventArgs` 对象的属性,并向列表框添加一条消息:
```vb
Protected eventCounter As Integer = 0
Private Sub SomethingClicked(ByVal sender As Object, _
ByVal e As MouseButtonEventArgs)
eventCounter += 1
Dim message As String = "#" & eventCounter.ToString() & ":" & _
Environment.NewLine & " Sender: " & sender.ToString() & _
Environment.NewLine
lstMessages.Items.Add(message)
End Sub
Private Sub cmdClear_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
lstMessages.Items.Clear()
End Sub
```
在处理像 `MouseLeftButtonDown` 这样的冒泡事件时,传递给事件处理程序的 `sender` 参数始终提供对链中最后一个环节的引用。例如,如果事件在被处理之前从图像冒泡到 `StackPanel`,`sender` 参数将引用 `StackPanel` 对象。
在某些情况下,我们可能想要确定事件最初发生的位置。冒泡事件的事件参数对象提供了一个 `Source` 属性,该属性会告知我们最初引发事件的具体元素。对于键盘事件,这是事件发生时(例如按键时)具有焦点的控件;对于鼠标事件,这是事件发生时(例如点击鼠标按钮时)鼠标指针下方的最顶层元素。不过,`Source` 属性可能会比我们期望的更详细。例如,若点击按钮背景的空白区域,`Source` 属性会提供对实际绘制所点击背景部分的 `Shape` 或 `Path` 对象的引用。
除了 `Source` 属性,冒泡事件的事件参数对象还提供了一个名为 `Handled` 的布尔属性,该属性允许我们抑制事件。例如,若在 `StackPanel` 中处理 `MouseLeftButtonDown` 事件并将 `Handled` 设置为 `True`,`StackPanel` 将不会触发 `MouseLeftButtonDown` 事件。结果是,当点击 `StackPanel`(或其内部的某个元素)时,`MouseLeftButtonDown` 事件不会到达按钮,`Click` 事件也永远不会触发。在构建自定义控件时,我们可以使用这种技术(例如,当我们已经处理了用户的按钮点击操作,并且不希望更高级别的元素参与其中时)。
需要注意的是,WPF提供了一种后门机制,允许代码接收被标记为已处理(通常会被忽略)的事件,而Silverlight不具备此功能。
## 3. 鼠标处理
在Silverlight应用程序中,几乎都会使用 `MouseLeftButtonDown` 事件。然而,关于鼠标事件的处理还有很多需要学习的地方。接下来,我们将探讨如何响应右键点击、鼠标移动和鼠标滚轮操作,还会学习如何捕获鼠标(以便在鼠标移开时仍能继续处理其事件)、如何模拟拖放操作以及如何更改鼠标光标。
### 3.1 右键点击
默认情况下,在Silverlight应用程序的任何位置右键点击时,会弹出一个Silverlight菜单。该菜单包含一个名为 “Silverlight” 的命令,点击它会打开一个标签式窗口,我们可以在其中更改Silverlight设置。此外,如果创建的应用程序支持在浏览器外安装,该菜单还会有第二个命令用于安装应用程序。
我们可能会决定处理某些元素(甚至整个窗口)的右键点击事件,以提供更专业的功能。例如,当用户右键点击特定元素时,我们可能希望显示一个带有该元素命令的自定义上下文菜单。尽管Silverlight不包含上下文菜单控件,但我们可以从Silverlight工具包(http://silverlight.codeplex.com)轻松获取一个。然后,我们可以使用它为任何控件附加右键点击菜单。
不过,这里有一个问题。即使显示了我们自己的上下文菜单,`MouseRightButtonDown` 事件仍会冒泡到应用程序的顶层,导致Silverli
0
0
复制全文
相关推荐









