Gil*_*lad 8 c# wpf routedevents
我是WPF的新手.我试图理解MouseDownEvent和PreviewMouseDownEvent之间的区别.
我理解WPF事件策略,我理解MouseDown事件是一个冒泡事件,PreviewMouseDown是一个隧道事件.
我也理解这些事件被触发的顺序 - 根据MSDN概述http://msdn.microsoft.com/en-us/library/ms742806.aspx#routing(这里有一个示例图).
所以我试着编写一些自己的代码,例如检查一下:
<Grid x:Name="grid" Width="250">
<StackPanel Mouse.MouseDown="StackPanel_MouseDown" PreviewMouseDown="StackPanel_PreviewMouseDown">
<WPFVisualizerExample:MyButton x:Name="B1" PreviewMouseDown="B1_PreviewMouseDown" MouseDown="B1_MouseDown" Margin="5,5,5,5">
<WPFVisualizerExample:MyButton x:Name="B2" PreviewMouseDown="B2_PreviewMouseDown" MouseDown="B2_MouseDown" Margin="5,5,5,5">
<WPFVisualizerExample:MyButton x:Name="B3" PreviewMouseDown="B3_PreviewMouseDown" MouseDown="B3_MouseDown" Margin="5,5,5,5">Click Me</WPFVisualizerExample:MyButton>
</WPFVisualizerExample:MyButton>
</WPFVisualizerExample:MyButton>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
我为每个事件(预览和非预览)都有一个事件处理程序,我想看看发生了什么,抛出了哪个事件(我为每个事件显示了一个消息框).
'MyButton'用户控件只是扩展基本Button并覆盖OnMouseDown和OnPreviewMouseDown来设置e.Handled false:
protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseDown(e);
e.Handled = false;
}
protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
e.Handled = false;
}
Run Code Online (Sandbox Code Playgroud)
(试过这个,没有这个).
根据MSDN概述(在上面的链接中),如果我有3个元素,那么事件路由应该如下:
根元素上的PreviewMouseDown(隧道).
中间元素#1上的PreviewMouseDown(隧道).
源元素#2上的PreviewMouseDown(隧道).
源元素#2上的MouseDown(气泡).
MouseDown(气泡)在中间元素#1上.
根元素上的MouseDown(气泡).
所以我希望根据上面的内容显示消息框.出于某种原因 - 我不明白只会抛出预览事件(根据MSDN所说的Preview_B1 => Preview_B2 => Preview_B3).我的期望是:Preview_B1 => Preview_B2 => Preview_B3 => NonPreview_B3 => NonPreview_B2 => NonPreview_B1.
但是非预览事件根本没有被抛出.
所以基本上我不理解事件的路由,从MSDN概述我理解路由从根元素开始,向下(隧道)到源元素然后备份(冒泡)到根元素,但是这个不是在实践中发生的事情.
对我来说理解这些事件是如何运作非常重要,我可能会错过 - 理解这里的基本内容,我们将非常感谢您的帮助.
THANX!-Gili
由于Button控件的功能是生成Click事件(或触发命令),因此它对鼠标事件的处理方式与其他控件略有不同.当Button收到PreviewMouseDown事件时,它会将其转换为Click事件,取消Preview和MouseDown冒泡事件的任何进一步隧道.根据Button的ClickMode设置,这有一些变化.如果您更愿意使用鼠标事件本身,您可以使用ContentControl(尝试它,您应该看到您的预期),但您可能会发现在大多数情况下使用Button.Click要容易得多.
UPDATE
您的代码中必定还有其他内容导致事件路由停止.这是一个类似于你的例子,我验证了它显示了预期的输出(添加了一些样式以使元素明显):
<Window.Resources>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="PaleGreen" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Tag="Panel" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
<ContentControl BorderBrush="Red" Tag="C1" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
<ContentControl BorderBrush="Green" Tag="C2" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
<ContentControl Content="Click Me" BorderBrush="Blue" Tag="C3" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown"/>
</ContentControl>
</ContentControl>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
和简单的处理程序写入Debug:
private void PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine((sender as FrameworkElement).Tag + " Preview");
}
private void MouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine((sender as FrameworkElement).Tag + " Bubble");
}
Run Code Online (Sandbox Code Playgroud)
调试输出(如果单击中心文本)是:
面板预览
C1预览
C2预览
C3预览
C3气泡
C2气泡
C1气泡
面板气泡
归档时间: |
|
查看次数: |
11472 次 |
最近记录: |