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

发布于 2024-11-25 09:15:53 字数 1263 浏览 0 评论 0原文

我正在编写一个自定义控件,并且希望当用户单击控件时该控件从编辑状态切换到正常状态。我正在处理 LostFocus 事件,当用户离开或单击另一个可聚焦的控件时,这会有所帮助。但是,如果他们不单击可聚焦的内容,它就不会切换出编辑状态。因此,我想到了两个解决方案:

  • 当进入编辑状态时,沿着树向上走到最顶部的元素,并为 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;
}
  • 使用 Mouse.PreviewMouseDownOutsideCapturedElement 并向我的控件添加一个处理程序。在处理程序中,我会将控件踢出其编辑状态。但我似乎没有让这个事件发生。 Mouse.PreviewMouseDownOutsideCapturedElement 何时启动?

示例代码:

AddHandler( Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler( EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent ), true );

I'm writing a custom control and I'd like the control to switch from an editing state to it's normal state when a user clicks off of the control. I'm handling the LostFocus event and that helps when a user tabs away or if they click on to another control that's Focusable. But if they don't click on something Focusable, it won't switch out of it's editing state. So I have two solutions in mind:

  • Walk up the tree to the top most element when it goes in to an editing state and add a handler for MouseDownEvent (and handle "handled" events). In the handler I'd kick the control out of it's editing state and remove the handler from the top most element. This seems like a bit of a hack, but it would probably work well.

Example code:

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;
}
  • Use Mouse.PreviewMouseDownOutsideCapturedElement and add a handler to my control. In the handler I'd kick the control out of it's editing state. But I don't seem to get the event to fire. When does the Mouse.PreviewMouseDownOutsideCapturedElement get kicked off?

Example code:

AddHandler( Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler( EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent ), true );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

哭泣的笑容 2024-12-02 09:15:53

只是为了澄清关于鼠标焦点提供的答案 - 它很有用,但我必须做一些进一步的挖掘和清理才能得到实际工作的东西:

我试图实现类似组合框的东西并且需要类似的行为 - 以获得下拉菜单单击其他内容时消失,而控件不知道其他内容是什么。

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

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

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

    private void AddHandler()
    {
        AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true);
    }

您还需要在适当的点坚持+删除处理程序,但为了清楚/简洁起见,我将其留在这里。

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

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

Just to clarify the answer provided about mouse focus - it was useful but I had to do some further digging + mucking about to get something that actually worked:

I was trying to implement something like a combobox and needed similar behaviour - to get the drop down to disapear when clicking on something else, without the control having knowledge of what something else was.

I had the following event for a drop down button:

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

The CaptureMode.SubTree means you only get events that are outside the control and any mouse activity in the control is passed through to things as normal. You dont have the option to provide this Enum in UIElement's CaptureMouse, this means you will get calls to HandleClickOutsideOfControl INSTEAD of calls to any child controls or other handlers within the control. This is the case even if you dont subscribe to the events they are using - full Mouse capture is a bit too much!

    private void AddHandler()
    {
        AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true);
    }

You would also need to hang on to + remove the handler at the appropriate points but I've left that out here for the sake of clarity/brevity.

Finally in the handler you need to release the capture again.

    private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
    {
        //do stuff (eg close drop down)
        ReleaseMouseCapture();
    }
北风几吹夏 2024-12-02 09:15:53

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

Capture the mouse.
When an object captures the mouse, all mouse related events are treated as if the object with mouse capture perform the event, even if the mouse pointer is over another object.

再可℃爱ぅ一点好了 2024-12-02 09:15:53

我通常会获取父窗口并添加预览处理程序,即使已经处理过。有时,当 MouseCapture 不够时,此技术会派上用场:

Window.GetWindow(this).AddHandler
(
    UIElement.MouseDownEvent,
    (MouseButtonEventHandler)TextBox_PreviewMouseDown,
    true
);

I usually get the parent window and add a preview handler, even if already handled. Sometimes when MouseCapture is not enough, this technique comes handy:

Window.GetWindow(this).AddHandler
(
    UIElement.MouseDownEvent,
    (MouseButtonEventHandler)TextBox_PreviewMouseDown,
    true
);
风吹雨成花 2024-12-02 09:15:53

我会以不同的方式处理这个问题 - 当用户单击表单的其他部分时,让包含控件的表单从控件中删除焦点。

让控件实际上失去焦点比尝试让控件“模拟”在某些情况下失去焦点要干净得多,而事实上并没有。请记住,除非控件确实失去焦点,否则它仍然会接受键盘输入等内容。

I would approach this a different way - have the form that contains the control remove focus from the control when a user clicks on another part of the form.

Having the control actually loose focus is far cleaner than attempting to have the control "simulate" focus being lost in certain situations, when in fact it hasn't. Bear in mind that unless the control has really lost focus it will still accept things like keyboard input.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文