我正在编写一个自定义控件,当用户点击控件时,我希望控件从编辑状态切换到正常状态。我正在处理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 );
答案 0 :(得分:35)
只是为了澄清关于鼠标焦点的答案 - 它很有用,但我不得不进一步挖掘+捣乱以获得实际工作的东西:
我试图实现像组合框这样的东西并且需要类似的行为 - 当点击其他东西时,让下拉消失,而没有控件知道其他东西是什么。
我有一个下拉按钮的以下事件:
private void ClickButton(object sender, RoutedEventArgs routedEventArgs)
{
//do stuff (eg activate drop down)
Mouse.Capture(this, CaptureMode.SubTree);
AddHandler();
}
CaptureMode.SubTree意味着您只能获取控件之外的事件,并且控件中的任何鼠标活动都会正常传递给事物。你没有选择在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();
}
答案 1 :(得分:13)
捕获鼠标。 当一个对象捕获鼠标时,所有与鼠标相关的事件都会被视为具有鼠标捕获的对象执行该事件,即使鼠标指针位于另一个对象上也是如此。
答案 2 :(得分:1)
我通常会获得父窗口并添加预览处理程序,即使已经处理过。有时当MouseCapture不够时,这种技术很方便:
Window.GetWindow(this).AddHandler
(
UIElement.MouseDownEvent,
(MouseButtonEventHandler)TextBox_PreviewMouseDown,
true
);
答案 3 :(得分:0)
我会以不同的方式处理 - 当用户点击表单的其他部分时,让包含控件的表单从控件中移除焦点。
让控件实际松散焦点比在某些情况下试图控制“模拟”焦点丢失要清晰得多,实际上它没有。请记住,除非控件确实失去焦点,否则它仍会接受键盘输入等内容。