Как элемент управления может обрабатывать щелчок мыши вне этого элемента управления? - PullRequest
24 голосов
/ 20 июля 2011

Я пишу пользовательский элемент управления, и я хотел бы, чтобы элемент управления переключался из состояния редактирования в нормальное состояние, когда пользователь щелкает элемент управления.Я обрабатываю событие 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;
}
  • Используйте Mouse.PreviewMouseDownOutsideCapturedElement и добавьте обработчик в мойконтроль.В обработчике я бы выкинул элемент управления из его состояния редактирования.Но я, кажется, не получаю событие, чтобы стрелять.Когда запускается Mouse.PreviewMouseDownOutsideCapturedElement?

Пример кода:

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

Ответы [ 4 ]

35 голосов
/ 25 января 2013

Просто чтобы прояснить ответ о фокусировке мыши - это было полезно, но мне пришлось немного покопаться, чтобы получить что-то, что действительно сработало:

Я пытался реализовать что-то вроде выпадающего списка и нуждался в похожем поведении - чтобы раскрывающийся список исчезал при нажатии на что-то другое, без элемента управления, обладающего знанием того, что еще было.

У меня было следующее событие для кнопки выпадающего меню:

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

CaptureMode.SubTree означает, что вы получаете только те события, которые находятся вне элемента управления, и любая активность мыши в элементе управления передается вещам, как обычно. У вас нет возможности предоставить этот Enum в CaptureMouse UIElement, это означает, что вы получите вызовы HandleClickOutsideOfControl INSTEAD для вызовов любых дочерних элементов управления или других обработчиков внутри элемента управления. Это так, даже если вы не подписываетесь на события, которые они используют - полный захват мыши - это слишком много!

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

Вы также должны были бы удержать + удалить обработчик в соответствующих точках, но я оставил это здесь для ясности / краткости.

Наконец, в обработчике вам нужно снова освободить захват.

    private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
    {
        //do stuff (eg close drop down)
        ReleaseMouseCapture();
    }
13 голосов
/ 20 июля 2011

Захват мыши.Когда объект захватывает мышь, все связанные с мышью события обрабатываются так, как будто объект с захватом мыши выполняет событие, даже если указатель мыши находится над другим объектом.

1 голос
/ 05 октября 2017

Я обычно получаю родительское окно и добавляю обработчик предварительного просмотра, даже если он уже обработан. Иногда, когда MouseCapture недостаточно, эта техника оказывается полезной:

Window.GetWindow(this).AddHandler
(
    UIElement.MouseDownEvent,
    (MouseButtonEventHandler)TextBox_PreviewMouseDown,
    true
);
0 голосов
/ 20 июля 2011

Я бы подошел к этому по-другому - форма, содержащая элемент управления, удаляет фокус с элемента управления, когда пользователь нажимает на другую часть формы.

Наличие элемента управления на самом деле потеря фокуса намного чище, чем попытка сделать так, чтобы элемент управления "имитировал" потерю фокуса в определенных ситуациях, хотя на самом деле это не так. Имейте в виду, что если элемент управления действительно не потерял фокус, он все равно будет принимать такие вещи, как ввод с клавиатуры.

...