2016-11-10 87 views
0

通常,如果我們有一個FrameworkElement,我們無法從另一個Thread更新其屬性。因爲它拋出一個ExceptionWpf TextBox.Text通過綁定在另一個線程中更新

public async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    await Task.Run(() => { MyTextBox.Background = new SolidBrushColor(Colors.Yellow); } 
} 

:例如,給定一個名爲TextBoxMyTextBox,我們不能這樣做,因爲不同的線程擁有它

調用線程不能訪問該對象。

無論我們可以通過修改Background通過Binding(在另一個Thread

<TextBox Name="MyTextBox" Background="{Binding BoundBackground}"/> 

在視圖模型設置它:

public async void SomeOperation() 
{ 
    await Task.Run(() => { BoundBackground = new SolidBrushColor(Colors.Yellow); } 
} 

因爲同樣的Exception被拋出。

現在,這裏是「奇怪的」行爲。如果你想直接從另一個Thread更新Text屬性,像這樣:

public async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    await Task.Run(() => { MyTextBox.Text = "new text"; } 
} 

它拋出同樣的預期Exception,但如果你綁定Text屬性是這樣的:

<TextBox Text="{Binding BoundText}"/> 

,並更新它從另一個Thread由ViewModel:

public async void SomeOperation() 
{ 
    await Task.Run(() => { BoundText = "new text"; } 
} 

它神奇地工作KS。

我注意到這種行爲也爲ProgressBarValue屬性。

這是一個錯誤,還是由設計製造,爲什麼?

+0

我只能想象它的財產變更通知爲你工作。 BoundText的類型是什麼? – sellotape

+0

@sellotape它顯然是一個字符串,否則我怎樣才能分配「新文本」值並將其綁定到Text屬性? –

回答

3

無論我們可以通過綁定(在另一個線程 )

這是不正確的修改背景。 WPF Binding會自動將該值封送回調度員線程(除非他們使用ObservableCollection<T>,但這是另一個話題)。

爲什麼你會得到一個InvalidOperationException,而試圖通過Binding設置Background屬性的原因,是您創建一個後臺線程SolidColorBrush並嘗試使用它的調度線程的事實。在返回之前,請在該畫筆上撥打Freeze()(在您的Task中),並且您不會再有任何異常,因爲任何線程都可以使用「凍結」Freezable

此外,這就是爲什麼多線程Binding s爲您的示例工作的所有其他屬性。