1

我有一个UserControl包含一个TextBox. 当用户控件变得可见时,我给予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);
    }
}
4

3 回答 3

3

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

如果这可行,那么我怀疑在this.IsVisibleChanged布局面板更新子控件之前引发了该事件,即InputTextBox当您将焦点放在没有BeginInvoke.

于 2012-12-13T12:28:12.840 回答
2

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

于 2012-12-13T12:07:26.367 回答
1

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

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

为了阻止您使用 Dispatcher 并尝试使用它来执行它不适合的神奇神秘壮举,请确保您熟悉Dispatcher.CurrentDispatcher属性及其区别(我见过一些真正糟糕的代码,因为开发人员没有意识到这一点)。

有关与 UI 元素关联的 Dispatcher 的良好概述,请查看这篇文章:MSDN 高级 WPF:线程模型。请注意VerifyAccess()在尝试操作控件的操作之前调用的示例代码。

于 2012-12-13T12:33:52.837 回答