我们有一个自定义控件,其中有一些' commit' LostFocus事件中的逻辑,如果用户移动到应用程序的不同部分,则触发该事件。
出现问题的原因是工具栏和应用程序的其他区域有几个按钮,其中包括可聚焦的'属性设置为False。因此,当他们被点击时,他们各自的行动都会触发,但是我们的控制仍然没有提交其更改,这会导致问题。
由于我们的UI本质上是模块化/动态的,并且因为它只是良好的编码实践,所以这些区域彼此之间并不了解,因此我们不能简单地在按钮中添加代码处理程序来进行控制提交。我们的控制需要通过点击来实现自身之外的东西。
我们最初的尝试是在我们的控件的GotFocus中使用类级事件处理程序,就像这样......
EventManager.RegisterClassHandler(
typeof(FrameworkElement),
PreviewMouseDownEvent,
new RoutedEventHandler(MyControl_PreviewMouseDownHandler));
private void MyControl_PreviewMouseDown(object sender, RoutedEventArgs e)
{
// Exit if the sender isn't the original source.
// This is because we want the deepest-clicked item, but also only want to process this once
if(sender != e.OriginalSource)
return;
var frameworkElement = (FrameworkElement)sender;
// If the clicked item is a descendant of ThisControl, do nothing.
if(frameworkElement.IsDescendantOf(NameOfMyControlInstance))
return;
CommitChanges();
// Unsubscribe class handler here
??? Can't do!
}
如果我们的控制失去了焦点,我们只需提交更改并取消订阅。此外,如果处理程序已触发,但OriginalSource不在我们的控制范围内,我们也会提交更改并取消订阅处理程序。问题是你不能取消订阅类处理程序!为什么我不知道。
那么我们如何才能告诉用户点击我们控制之外的某些内容并不能锁定焦点呢?