2016-11-10 5 views
0

通常、FrameworkElementがある場合、そのプロパティを別のThreadから更新することはできません。それはExceptionをスローするのでWpf TextBox.Textバインドで別のスレッドで更新可能

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

別のスレッドがそれを所有しているので、呼び出し元のスレッドがこのオブジェクトにアクセスすることはできません例えば、MyTextBoxという名前TextBox与え、我々はこれを行うことはできません。

どちらもない我々はViewModelににそれを設定する(別のThread中)

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

Bindingを通じてBackgroundを変更することができます。

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}"/> 

とアップデートそれは別のからViewModelによってThread

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

それは魔法のようにワks。

ProgressBarValueプロパティでもこの現象が発生しています。

これはバグですか?そうではありませんか?設計によって作られた理由は何ですか?

+0

私はそれがあなたのために働くプロパティー変更通知だと想像することができます。 BoundTextのタイプは何ですか? – sellotape

+0

@sellotapeそれは明らかに文字列です。そうでなければ、「新しいテキスト」の値を割り当ててTextプロパティにバインドできますか? –

答えて

3

どちらも私たちは真実ではありません

(別 のスレッドで)の結合を介して背景を変更することはできません。 WPF Bindingは、ディスパッチャスレッドに値を自動的にマーシャリングします(ObservableCollection<T>を使用しない限り、別のトピックです)。

Bindingを通じてBackgroundプロパティを設定しようとしているときに、あなたがInvalidOperationExceptionを取得している理由は、あなたがバックグラウンドスレッドでSolidColorBrushを作成し、ディスパッチャスレッド上でそれを使用しようとしているという事実です。 (Task)に戻す前にそのブラシにFreeze()を呼び出してください。「フリーズした」Freezableはどんなスレッドでも使用できるので、もう例外はありません。

また、それがあなたの例の他のすべてのプロパティのマルチスレッドBindingを使用する理由です。

関連する問題