(建议大家使用工具 snoop,可以到blois.us/Snoop下载安装。)
先来了解下什么是WPF里的路由事件
我们创建一个WPF应用程序,代码如下:
<Window x:Class="Wpfceshi.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" MouseDown="Window_MouseDown" >
<Grid MouseDown="Grid_MouseDown" x:Name="grid">
<Button Height="30" Width="100" Content="点击我" MouseDown="Button_MouseDown"/>
</Grid>
</Window>
using System.Windows;
using System.Windows.Input;
namespace Wpfceshi
{
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Window被点击");
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Grid被点击");
}
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Button被点击");
}
}
}
调试运行,鼠标右键点击按钮,会依次弹出三个对话框。(注意一定是鼠标右键,否则引发不了事件)
这里大家也许就会问了,我点击的是按钮,为什么Grid和Window也会引发事件呢?其实这就是路由事件的机制,引发的事件由源元素逐级传到上层的元素,Button—>Grid—>Window,这样就导致这几个元素都接收到了事件。
那么如何让Grid和Window不处理这个事件呢?
我们只需要在Button_MouseDown这个方法中加上e.Handled = true; 这样就表示事件已经被处理,其他元素不需要再处理这个事件了。
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Button被点击");
e.Handled = true;
}
这时如果我们需要Grid也参与处理这个事件该怎么做呢?我们只需要给他AddHandler即可。
修改代码如下
public Window1()
{
InitializeComponent();
grid.AddHandler(Grid.MouseDownEvent, new RoutedEventHandler(Grid_MouseDown1), true);
}
再加上这个方法
private void Grid_MouseDown1(object sender, RoutedEventArgs e)
{
MessageBox.Show("Grid被点击");
}
到此大家应该对路由事件有大概的认识了吧。
上面我们看到的只是路由事件中的一种方式:气泡。还有两种:隧道、直接。
总结:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" PreviewMouseDown="Window_PreviewMouseDown" >
<Grid PreviewMouseDown="Grid_PreviewMouseDown" x:Name="grid">
<Button Height="30" Width="100" Content="点击我" PreviewMouseDown="Button_PreviewMouseDown"/>
</Grid>
</Window>
using System.Windows;
using System.Windows.Input;
namespace Wpfceshi
{
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Button被点击");
}
private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Grid被点击");
}
private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Window被点击");
}
}
}
可以看到,隧道事件的传递刚好与气泡事件相反。
文章就到这里吧,希望对你有帮助。