Ответ 1
Захват мыши. Когда объект захватывает мышь, все связанные с мышью события обрабатываются так, как если бы объект с захватом мыши выполнял событие, даже если указатель мыши находится над другим объектом.
Я пишу настраиваемый элемент управления, и я бы хотел, чтобы элемент управления переключился с состояния редактирования на нормальное состояние, когда пользователь отключился от элемента управления. Я обрабатываю событие LostFocus, и это помогает, когда пользователь уходит или нажимает на другой элемент управления, который является Focusable. Но если они не нажимают на что-то 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 );
Захват мыши. Когда объект захватывает мышь, все связанные с мышью события обрабатываются так, как если бы объект с захватом мыши выполнял событие, даже если указатель мыши находится над другим объектом.
Просто, чтобы прояснить ответ, предоставленный в отношении фокуса мыши - это было полезно, но я должен был сделать еще одно копание + выкидывание, чтобы получить что-то, что действительно сработало:
Я пытался реализовать что-то вроде combobox и нуждался в подобном поведении - чтобы получить падение вниз, чтобы исчезнуть при нажатии на что-то еще, без контроля, знающего, что что-то еще.
У меня было следующее событие для кнопки "вниз":
private void ClickButton(object sender, RoutedEventArgs routedEventArgs)
{
//do stuff (eg activate drop down)
Mouse.Capture(this, CaptureMode.SubTree);
AddHandler();
}
CaptureMode.SubTree означает, что вы получаете только события, которые находятся вне элемента управления, и любая активность мыши в элементе управления передается в обычное состояние. У вас нет возможности предоставить этот Enum в UIElement CaptureMouse, это означает, что вы вызовете 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();
}
Я бы подошел к этому по-другому - получив форму, содержащую элемент управления, удалите фокус с элемента управления, когда пользователь нажимает на другую часть формы.
Наличие элемента управления на самом деле. Свободный фокус намного чище, чем попытка сбросить фокус в определенных ситуациях, когда на самом деле это не так. Имейте в виду, что, если элемент управления не потерял фокус, он все равно примет такие вещи, как ввод с клавиатуры.
Обычно я получаю родительское окно и добавляю обработчик предварительного просмотра, даже если он уже обработан. Иногда, когда MouseCapture недостаточно, этот метод подходит:
Window.GetWindow(this).AddHandler
(
UIElement.MouseDownEvent,
(MouseButtonEventHandler)TextBox_PreviewMouseDown,
true
);