TextChanged是路由事件类别中的直接事件

时间:2018-02-20 18:25:38

标签: c# wpf routed-events

我知道'Onclick'是Direct routed事件之一,

直接路由事件是由源本身处理的事件,但仍然不清楚所有直接路由事件是什么,所有在互联网上给出的示例仅使用'OnClick'进行直接路由事件。

有人可以提供所有直接路由事件的列表吗?

1 个答案:

答案 0 :(得分:2)

  

我知道OnClick是直接路由事件之一

如果您指的是ButtonBase.OnClick,那么它实际上是直接事件;这是一个冒泡的事件。

  

TextChanged是路由事件类别中的直接事件吗?

如果你指的是TextBox.TextChanged,那么不;它也是一个冒泡的事件。

  

有人可以提供所有直接路由事件的列表吗?

从C#Interactive窗口轻松完成:

> #r "WindowsBase"
> #r "PresentationCore"
> #r "PresentationFramework"
> using System.Windows;
> using System.Linq;
> using System.Runtime.CompilerServices;
> var types = from t in typeof(FrameworkElement).Assembly.GetTypes()
.             where typeof(FrameworkElement).IsAssignableFrom(t)
.             select t;
> foreach (var t in types) RuntimeHelpers.RunClassConstructor(t.TypeHandle);
> var events = from e in EventManager.GetRoutedEvents()
.              where e.RoutingStrategy == RoutingStrategy.Direct
.              select $"{e.OwnerType.Name}.{e.Name}";
> foreach (var e in events) Console.WriteLine(e);

结果:

FrameworkElement.SizeChanged  
FrameworkElement.Loaded  
FrameworkElement.Unloaded  
ToolTipService.ToolTipOpening  
ToolTipService.ToolTipClosing  
UIElement.PreviewMouseLeftButtonDown  
UIElement.MouseLeftButtonDown  
UIElement.PreviewMouseLeftButtonUp  
UIElement.MouseLeftButtonUp  
UIElement.PreviewMouseRightButtonDown  
UIElement.MouseRightButtonDown  
UIElement.PreviewMouseRightButtonUp  
UIElement.MouseRightButtonUp  
Mouse.MouseEnter  
Mouse.MouseLeave  
Stylus.StylusEnter  
Stylus.StylusLeave  
Touch.TouchEnter  
Touch.TouchLeave  
Control.PreviewMouseDoubleClick  
Control.MouseDoubleClick  
Calendar.SelectedDatesChanged  
DatePicker.SelectedDateChanged  
VirtualizingStackPanel.CleanUpVirtualizedItemEvent

请注意,上面的代码只会显示路由事件。它不会向您展示普通的旧CLR事件。

随访

  

在你的结果中,PreviewMouseLeftButtonDown是一个直接事件,但据我所知它的隧道事件和类似的MouseLeftButtonDown是冒泡事件,请澄清。

这是一个直接的事件。检查源代码:

/// <summary>
///     Declaration of the routed event reporting the left mouse button was pressed
/// </summary>
public static readonly RoutedEvent PreviewMouseLeftButtonDownEvent = 
    EventManager.RegisterRoutedEvent("PreviewMouseLeftButtonDown", 
                                     RoutingStrategy.Direct,
                                     typeof(MouseButtonEventHandler),
                                     _typeofThis);

你的困惑可能源于它行为就像一个隧道事件。特定于按钮的鼠标事件是一种“子事件”&#39 ;;当某些其他事件到达给定的UI元素时,它们会被引发。例如,当LeftMouseButtonDown到达MouseButtonDown ChangedButton时,Left会被触发。 Preview事件也是如此。

亲眼看看:

private static void OnPreviewMouseDownThunk(object sender, MouseButtonEventArgs e)
{
    if(!e.Handled)
    {
        UIElement uie = sender as UIElement;

        if (uie != null)
        {
            uie.OnPreviewMouseDown(e);
        }
        else
        {
            ContentElement ce = sender as ContentElement;

            if (ce != null)
            {
                ce.OnPreviewMouseDown(e);
            }
            else
            {
                ((UIElement3D)sender).OnPreviewMouseDown(e);
            }
        }
    }

    // Always raise this "sub-event", but we pass along the handledness.
    UIElement.CrackMouseButtonEventAndReRaiseEvent((DependencyObject)sender, e);
}

private static void CrackMouseButtonEventAndReRaiseEvent(DependencyObject sender, MouseButtonEventArgs e)
{
    RoutedEvent newEvent = CrackMouseButtonEvent(e);

    if (newEvent != null)
    {
        ReRaiseEventAs(sender, e, newEvent);
    }
}

private static RoutedEvent CrackMouseButtonEvent(MouseButtonEventArgs e)
{
    RoutedEvent newEvent = null;

    switch(e.ChangedButton)
    {
        case MouseButton.Left:
            if(e.RoutedEvent == Mouse.PreviewMouseDownEvent)
                newEvent = UIElement.PreviewMouseLeftButtonDownEvent;
            else if(e.RoutedEvent == Mouse.MouseDownEvent)
                newEvent = UIElement.MouseLeftButtonDownEvent;
            else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent)
                newEvent = UIElement.PreviewMouseLeftButtonUpEvent;
            else
                newEvent = UIElement.MouseLeftButtonUpEvent;
            break;
        case MouseButton.Right:
            if(e.RoutedEvent == Mouse.PreviewMouseDownEvent)
                newEvent = UIElement.PreviewMouseRightButtonDownEvent;
            else if(e.RoutedEvent == Mouse.MouseDownEvent)
                newEvent = UIElement.MouseRightButtonDownEvent;
            else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent)
                newEvent = UIElement.PreviewMouseRightButtonUpEvent;
            else
                newEvent = UIElement.MouseRightButtonUpEvent;
            break;
        default:
            // No wrappers exposed for the other buttons.
            break;
    }
    return ( newEvent );
}

因此,虽然按钮特定事件是直接事件,但它们会依赖于冒泡和隧道事件,因此它们出现以遵循这些路由策略。

对于所有意图和目的,您可以它们视为冒泡和隧道事件,无论它们是如何注册的。