【问题标题】:Why does setting keyboard focus from code behind require Dispatcher.BeginInvoke?为什么从后面的代码设置键盘焦点需要 Dispatcher.BeginInvoke?
【发布时间】:2013-07-20 02:44:13
【问题描述】:

我有一个包含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没有得到焦点?
  • 是的,我的意思是根本没有将焦点放在 TextBox 上。

标签: c# wpf user-controls textbox dispatcher


【解决方案1】:

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

如果这可行,那么我怀疑在布局面板更新子控件之前引发了 this.IsVisibleChanged 事件,即当您将焦点放在没有 BeginInvoke 的情况下,InputTextBox 可能仍然不可见。

【讨论】:

  • 这很有效。我已经做了一些测试,可以确认在案例 2 中,我试图在 TextBox 可见之前设置焦点。在调度程序上排队焦点更改意味着稍后会调用它(即在调度程序线程完成渲染 TextBox 之后)。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    为了阻止您使用 Dispatcher 并试图使用它来执行它不适合的神奇神秘壮举,请确保您熟悉 Dispatcher.CurrentDispatcher 属性及其区别(I'由于开发人员没有意识到这一点,我们已经看到了一些非常糟糕的代码。

    有关与 UI 元素关联的 Dispatcher 的详细概述,请查看这篇文章:MSDN Advanced WPF: Threading Model。请注意,在尝试操作控件的操作之前调用 VerifyAccess() 的示例代码。

    【讨论】:

    • 感谢您抽出宝贵时间提供帮助。在这种情况下,我相信事件是在 UI 线程上引发的,但是这里的信息仍然非常有价值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2014-04-22
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多