2012-12-13 63 views
1

我有一個UserControl包含TextBox。當用戶控件變得可見時,我給出了焦點TextBox。有人可以澄清爲什麼我必須使用Dispatcher來做到這一點嗎?爲什麼設置背後的代碼鍵盤焦點需要Dispatcher.BeginInvoke?

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); 
    } 
} 
+0

你有更改運行線程的代碼嗎? – SWeko

+0

當你說「不工作」,你不會得到一個異常,只是InputTextBox沒有得到重點? – Clemens

+0

是的,我的意思是說重點不在TextBox中。 – Coder1095

回答

3

可以調用Keyboard.Focus(InputTextBox);在事件處理程序InputTextBox.IsVisibleChanged,而不是this.IsVisibleChanged

如果這樣做的話,我懷疑this.IsVisibleChanged事件是在佈局面板更新了子控件之前引發的,也就是說InputTextBox在您沒有BeginInvoke時將焦點放在它上面時仍然不可見。

+0

這是有效的,是有道理的。我已經做了一些測試,並且可以確認在情況2中,我正在嘗試在TextBox可見之前設置焦點。在調度器上排隊焦點變化意味着它稍後被調用(即在調度器線程已經完成渲染文本框之後)。 – Coder1095

2

大概是因爲IsVisibleChanged事件被另一個線程上提出(不是UI線)。

1

你操縱的控制屬於UI線程(因爲這是在創建它)。所有的控件自DispatcherObject派生,所以control.Dispatcher(或this.Dispatcher在控制範圍之內)會給你屬於控制創建的線程參考調度。

你再排隊在該事件處理程序是運行在從後臺線程調度器的操作。你爲什麼在後臺線程上運行?它是一個控制器,因此它受到主機的支配,猜測後臺線程上有一些編程邏輯會導致可見性發生變化(可能通過數據綁定),因此事件處理程序也會被調用後臺線程。

爲了阻止你與調度員一起瘋狂並試圖用它來執行它不適用的魔法神祕專長,請確保你熟悉Dispatcher.CurrentDispatcher屬性及其差異(我已經由於開發人員沒有意識到這一點,看到了一些真正糟糕的代碼)。

對於UI元素相關的檢查本文調度程序的一個很好的概述:MSDN Advanced WPF: Threading Model。請注意,在嘗試操作控件的操作之前調用VerifyAccess()的示例代碼。

+0

謝謝你抽出時間幫忙。在這種情況下,我相信該事件正在UI線程中提出,但是這裏的信息仍然非常有價值。 – Coder1095

相關問題