为什么从代码背后设置键盘焦点需要Dispatcher.开始调用



我有一个包含TextBoxUserControl。当用户控件变得可见时,我给出TextBox焦点。有人能澄清一下为什么我必须使用Dispatcher吗?

public MyUserControl() 
{
InitializeComponent();
this.IsVisibleChanged += VisibilityChanged;
}

案例1(工作):

private void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.Visibility == Visibility.Visible)
{
this.Dispatcher.BeginInvoke((Action)delegate
{
Keyboard.Focus(this.InputTextBox);
}, DispatcherPriority.Render);
}
}

情况2(不起作用):

private void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.Visibility == Visibility.Visible)
{
Keyboard.Focus(InputTextBox);
}
}

您能在InputTextBox.IsVisibleChanged的事件处理程序中调用Keyboard.Focus(InputTextBox);而不是this.IsVisibleChanged吗?

如果这有效,那么我怀疑this.IsVisibleChanged事件是在布局面板更新子控件之前引发的,即当您在没有BeginInvoke的情况下关注InputTextBox时,它可能仍然不可见。

可能是因为IsVisibleChanged事件是在另一个线程上引发的(而不是在UI线程上)。

您正在操作的控件属于UI线程(因为它是在那里创建的)。所有控件都派生自DispatcherObject,因此control.Dispatcher(或控件内的this.Dispatcher)将为您提供属于创建控件的线程的Dispatcher的引用。

然后,您正在从事件处理程序运行的后台线程对该Dispatcher上的操作进行排队。为什么要在后台线程上运行?它是一个控件,因此受其主机的支配,猜测后台线程上有一些编程逻辑导致可见性发生变化(可能通过数据绑定),因此事件处理程序也会在该后台线程上调用。

为了防止您疯狂使用Dispatcher,并尝试使用它来执行非预期的神奇神秘壮举,请确保您熟悉Dispatcher。CurrentDispatcher属性及其差异(由于开发人员没有意识到这一点,我看到了一些非常糟糕的代码)。

有关与UI元素关联的Dispatcher的良好概述,请参阅本文:MSDN Advanced WPF:Threading Model。请注意,在尝试操作控件之前调用VerifyAccess()的示例代码。

相关内容

  • 没有找到相关文章

最新更新