我认为在这种情况下,您可以对路由事件进行有用的处理。有两种类型的事件:冒泡、直接和隧道。应注意Bubbling
和Tunneling
。冒泡事件上升逻辑树并向下隧道。下面是这里的图表:
所以那个事件向上/向下树,应该在每个控件上设置。通常,演示冒泡事件,应用此示例:
XAML
<Window x:Class="DemoRoutedEvents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" MouseUp="somethingClicked">
<Grid MouseUp="somethingClicked">
<StackPanel MouseUp="somethingClicked" Margin="0,0,10,0">
<Label x:Name="btnClickMe" Content="Click Me!" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="101,22,0,0" MouseUp="somethingClicked"/>
<CheckBox x:Name="chkhandle" Content="CheckBox" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="241,28,0,0" RenderTransformOrigin="-0.588,1.188"/>
<ListBox x:Name="lstEvents" HorizontalAlignment="Left" Height="604" VerticalAlignment="Top" Width="416" Margin="29,66,0,0"/>
</StackPanel>
</Grid>
</Window>
Code behind
public int eventCounter = 0;
private void somethingClicked(object sender, RoutedEventArgs e)
{
eventCounter++;
String message = "#" + eventCounter.ToString() + ":\r\n" +
" Sender: " + sender.ToString() + ":\r\n" +
" Source: " + e.Source + ":\r\n" +
" Original Source: " + e.OriginalSource;
lstEvents.Items.Add(message);
e.Handled = (bool)chkhandle.IsChecked;
if (e.Handled)
lstEvents.Items.Add("Completed");
}
Output
我试图针对多个面板和组件优化此过程。我创建了一个附加的依赖属性IsDebugEvent
,它属于EventBehaviours
. 原理很简单,我们获取一个事件处理程序,并为该类型的所有元素Control
(几乎所有它继承的 UIElements)设置它。对于 Grid、StackPanel、WrapPanel 等面板,Panel
是基类。
在处理程序中,我们找到ListBox
并显示面板的名称 s 导致事件的元素,仅用于测试。该示例使用事件PreviewMouseLeftButtonDown
(隧道),因为第一次触发是在 的事件Button.Click
,并且当它工作时,它与事件冲突MouseUp
。从这里引用:
ButtonBase 继承自 UIElement,Button 还可以访问为 UIElement 定义的所有鼠标按钮事件。因为 Button 会响应按钮按下而做一些事情,所以它会吞下冒泡事件(例如 MouseLeftButtonDown 和 MouseDown)。您仍然可以通过为隧道事件添加处理程序(例如 PreviewMouseLeftButtonDown 和 PreviewMouseDown)来检测这些较低级别的按钮按下事件。
XAML
<Window x:Class="AwayEventHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AwayEventHelp"
Title="MainWindow" Height="550" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<CheckBox Name="DebugCheckBox" Width="100" Height="30"
VerticalAlignment="Top"
Content="Debug event" IsChecked="False"
Checked="DebugCheckBox_Checked" Unchecked="DebugCheckBox_Unchecked" />
<StackPanel Name="LeftStackPanel" Width="150" local:EventBehaviours.IsDebugEvent="False"
HorizontalAlignment="Left" Background="BlanchedAlmond">
<Button Name="LeftButton1" Height="30" Content="LeftButton1" />
<Button Name="LeftButton2" Height="30" Content="LeftButton2" />
<Button Name="LeftButton3" Height="30" Content="LeftButton3" />
<Label Name="JustLabelLeft" Content="JustLabelLeft" Background="Azure" HorizontalContentAlignment="Center" />
</StackPanel>
<StackPanel Name="RightStackPanel" Width="150" local:EventBehaviours.IsDebugEvent="False"
HorizontalAlignment="Right" Background="Azure">
<Button Name="RightButton1" Height="30" Content="RightButton1" />
<Button Name="RightButton2" Height="30" Content="RightButton2" />
<Button Name="RightButton3" Height="30" Content="RightButton3" />
<Label Name="JustLabelRight" Content="JustLabelRight" Background="BlanchedAlmond" HorizontalContentAlignment="Center" />
</StackPanel>
<Grid Name="GridPanel" Width="100" Height="100" local:EventBehaviours.IsDebugEvent="False"
VerticalAlignment="Bottom" Background="CadetBlue">
<Label Name="LabelInGrid" Width="100" Height="50" Content="LabelInGrid" Background="AliceBlue" />
</Grid>
<ListBox Name="EventOutput" Width="180" Height="180" Background="AliceBlue" />
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void DebugCheckBox_Checked(object sender, RoutedEventArgs e)
{
EventBehaviours.SetIsDebugEvent(LeftStackPanel, true);
EventBehaviours.SetIsDebugEvent(RightStackPanel, true);
EventBehaviours.SetIsDebugEvent(GridPanel, true);
}
private void DebugCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
EventBehaviours.SetIsDebugEvent(LeftStackPanel, false);
EventBehaviours.SetIsDebugEvent(RightStackPanel, false);
EventBehaviours.SetIsDebugEvent(GridPanel, false);
}
}
public class EventBehaviours : DependencyObject
{
#region IsDebugEvent declaration
public static void SetIsDebugEvent(DependencyObject target, bool value)
{
target.SetValue(IsDebugEventProperty, value);
}
public static bool GetIsDebugEvent(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(IsDebugEventProperty);
}
public static readonly DependencyProperty IsDebugEventProperty =
DependencyProperty.RegisterAttached("IsDebugEvent",
typeof(bool),
typeof(EventBehaviours),
new UIPropertyMetadata(false, OnIsDebugEvent));
#endregion
private static void OnIsDebugEvent(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Panel MyPanel = sender as Panel;
if (e.NewValue is bool && ((bool)e.NewValue == true))
{
MyPanel.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
if (MyPanel.Children.Count != 0)
{
foreach (Control MyControl in MyPanel.Children)
{
MyControl.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
}
}
else
{
foreach (Control MyControl in MyPanel.Children)
{
MyControl.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
MyPanel.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(MyControl_PreviewMouseLeftButtonDown);
}
}
/// <summary>
/// Main handler of PreviewMouseLeftButtonDown event
/// </summary>
private static void MyControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
string OutInfo = string.Empty;
if (sender.GetType() == typeof(StackPanel))
{
StackPanel MyStackPanel = sender as StackPanel;
Grid MyGrid = MyStackPanel.Parent as Grid;
OutInfo = "PanelName: " + MyStackPanel.Name;
OutInfoInListBox(MyGrid, OutInfo);
}
else if (sender.GetType() == typeof(Grid))
{
Grid MyGrid = sender as Grid;
Grid MyMainGrid = MyGrid.Parent as Grid;
OutInfo = "PanelName: " + MyGrid.Name;
OutInfoInListBox(MyMainGrid, OutInfo);
}
else
{
Control MyControl = sender as Control;
Panel MyStackPanel = MyControl.Parent as Panel;
Grid MyGrid = MyStackPanel.Parent as Grid;
OutInfo = "ControlName: " + MyControl.Name;
OutInfoInListBox(MyGrid, OutInfo);
}
}
/// <summary>
/// Get ListBox and insert some info
/// </summary>
/// <param name="ParentGrid">Panel, where locate ListBox</param>
/// <param name="info">Just string</param>
private static void OutInfoInListBox(Grid ParentGrid, string info)
{
ListBox MyEventOutput = ParentGrid.FindName("EventOutput") as ListBox;
MyEventOutput.Items.Add(info);
}
}
Output
通过单击,在主题中CheckBox
设置依赖属性,从而导致我们设置处理程序的位置。如果取消选择in,则删除所有事件处理程序。IsDebugEvent
True
OnIsDebugEvent
CheckBox
要在启动时立即设置事件,您需要确保成功启动上的所有项目。这可以在 的情况下ContentRendered
完成Window
。