控件如何在该控件外部处理鼠标单击?

chr*_*son 25 c# wpf custom-controls mouseevent

我正在编写一个自定义控件,我希望控件在用户点击控件时从编辑状态切换到正常状态.我正在处理LostFocus事件,这有助于当用户选中时或者他们点击另一个可聚焦的控件时.但如果他们没有点击Focusable,它就不会切换出它的编辑状态.所以我有两个解决方案:

  • 当树进入编辑状态并为其添加处理程序MouseDownEvent(并处理"已处理"事件)时,将树向上移动到最顶层元素.在处理程序中,我将控件从其编辑状态中踢出,并从最顶层的元素中删除处理程序.这看起来有点像黑客,但它可能会运作良好.

示例代码:

private void RegisterTopMostParentMouseClickEvent()
{
   _topMostParent = this.FindLastVisualAncestor<FrameworkElement>();
   if ( _topMostParent == null )
      return;
   _topMostParent.AddHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ), true );
}

private void UnRegisterTopMostParentMouseClickEvent()
{
   if ( _topMostParent == null )
      return;
   _topMostParent.RemoveHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ) );
   _topMostParent = null;
}
Run Code Online (Sandbox Code Playgroud)
  • 使用Mouse.PreviewMouseDownOutsideCapturedElement并向我的控件添加处理程序.在处理程序中,我将控件从其编辑状态中踢出.但我似乎没有让事件发生.Mouse.PreviewMouseDownOutsideCapturedElement什么时候开始?

示例代码:

AddHandler( Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler( EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent ), true );
Run Code Online (Sandbox Code Playgroud)

Jon*_*Raa 36

只是为了澄清关于鼠标焦点的答案 - 这很有用,但我不得不进一步挖掘+捣乱以获得实际工作的东西:

我试图实现像组合框一样的东西并且需要类似的行为 - 当点击其他东西时让下拉消失,而没有控制权知道其他东西是什么.

我有一个下拉按钮的以下事件:

    private void ClickButton(object sender, RoutedEventArgs routedEventArgs)
    {
        //do stuff (eg activate drop down)
        Mouse.Capture(this, CaptureMode.SubTree);
        AddHandler();
    }
Run Code Online (Sandbox Code Playgroud)

CaptureMode.SubTree意味着您只获取控件之外的事件,并且控件中的任何鼠标活动都会正常传递给事物.你没有选择在UIElement的CaptureMouse中提供这个枚举,这意味着你将调用HandleClickOutsideOfControl INSTEAD来调用控件中的任何子控件或其他处理程序.即使您没有订阅他们正在使用的事件,情况也是如此 - 完全鼠标捕获有点太多了!

    private void AddHandler()
    {
        AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true);
    }
Run Code Online (Sandbox Code Playgroud)

您还需要在适当的位置继续+删除处理程序,但为了清晰/简洁起见,我已将其留在此处.

最后在处理程序中,您需要再次释放捕获.

    private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
    {
        //do stuff (eg close drop down)
        ReleaseMouseCapture();
    }
Run Code Online (Sandbox Code Playgroud)

  • 像TextBox这样的控件往往会在单击时释放caputre,因此每次控件上升`LostMouseCapture`事件时都必须重新附加处理程序.只是我的观察. (9认同)

Dmy*_*tin 13

捕获鼠标.当对象捕获鼠标时,所有与鼠标相关的事件都被视为具有鼠标捕获的对象执行事件,即使鼠标指针位于另一个对象上也是如此.

  • 我必须要小心的另一件事是,当你按下Windows键或其他应用程序启动时,我会丢失鼠标捕获而不会阻止我的控件处于编辑状态.所以我必须处理IsMouseCapturedChanged事件.例如,`private void CustomControlIsMouseCapturedChanged(object sender,DependencyPropertyChangedEventArgs e){if((bool)e.NewValue == false){IsEditing = false; } (4认同)
  • 所以这完美无缺.我所要做的就是当我进入编辑模式时捕获鼠标,然后当你点击它外面时,WPF自动将焦点从元素上移开.在我失去焦点后,我只需要小心ReleaseMouseCapture().谢谢! (2认同)
  • 由于 mousecaption,所有其他控件都将不可单击,或者单击不会发生在它们上。当鼠标悬停在元素上时,甚至元素也不再突出显示。怎么解决呢?这种行为不仅仅是不幸。 (2认同)