2009-07-25 15 views
2

InitializeComponentsの後のMy Windowコンストラクタで、オブジェクトを作成してDataGridにバインドする必要があります。オブジェクトの作成には時間がかかりすぎるため、ウィンドウの表示に時間がかかります。そこで私は、オブジェクトの作成をバックグラウンドスレッドに移し、dispatcher.invokeを実行してバインディングを実行することによって、UIスレッドに「委譲する」ことにしました。しかしこれは失敗する。WPF:UIスレッドとバックグラウンドスレッド間のオブジェクトの受け渡し

Dispatcher.invoke内にある矩形の可視性を設定しようとすると奇妙なことになりますが、それは動作しますがDataGrid.setbindingは機能しません!何か案は?バックグラウンドワーカーとthreadstartで同じことを試しましたが、同じエラーが発生しています。ディスパッチャ内で起きたことがデリゲートを呼び出すにもかかわらず、DataGridオブジェクトにアクセスできません。これがどういう仕組みか分かりません。どんな提案も大歓迎です。ありがとう!

StartupDelegate s = new StartupDelegate(CreateModel); 
s.BeginInvoke(delegate(IAsyncResult aysncResult) { s.EndInvoke(aysncResult); }, null); 

internal CreateModel() 
{ 
    Model d = new Model(); 
    Dispatcher.Invoke(DispatcherPriority.Normal, 
         new Action<Model>(
          delegate(Model d1) 
          { 
           mModel = d1; // mModel is a property defined in Window 
           Binding b = new Binding(); 
           b.Source = mModel; 
           MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); // << dies here with - The calling thread cannot access this object because a different thread owns it. 
          }    
} 

UPDATE: だけ一度に実行しますdispatchertimerを使用して終了。バインディングコードをTick代理人に渡すことができました。しかし、私はまだ上記のコードdoesntの理由が不思議です。

答えて

0

私は別の方法をお勧めします。

コードからバインドする必要はありません。代わりに、XAMLで定義する必要があります。

Model型のDependencyPropertyをウィンドウにもう1つ追加し、それを "CurrentModel"と呼び、その初期値をNULLに設定できます。あなたはすでにmModelというプロパティを持っているようですが、それはDependencyPropertyですか?

CurrentModelのBindingをDataGridまたはXAMLのいずれのコントロールにも定義できます。

代理人の最後では、Dispatcher.InvokeはCurrentModelのみを設定し、バインドは自動的に行われます。

+0

私はxamlではなく、nullにinitedプロパティを持つプロパティへのバインディングを設定しようとしました。そのため、デリゲートには1つの行mModel = d1しかありませんでした。しかし、何も起こらなかった。依存関係プロパティではなく、notifypropertychangedを実装する通常のプロパティです。 – Sharun

+0

オブジェクトがDependencyObjectから派生している(ウィンドウがある)場合、INotifyPropertyChangedは機能しません。同様の問題があっても、なぜDependencyPropertyに変更したのでしょうか? –

0

どのディスパッチャインスタンスでInvokeを呼び出していますか?

UIスレッドのものではなく、CreateModelを実行しているバックグラウンドスレッドのディスパッチャであると推測しています。

DataGridはコントロールであり、DispatcherObjectから派生しています。このような各オブジェクトは、所有者スレッドのディスパッチャをDispatcherプロパティで公開します。これは、コントロールのメソッドを呼び出すときに使用する必要があります。コールにディスパッチャを変更

は動作するはずです:

internal CreateModel() 
{ 
    Model d = new Model(); 

    // Invoke the action on the dispatcher of the DataGrid 
    MainDataGrid.Dispatcher.Invoke(DispatcherPriority.Normal, 
         new Action<Model>(
          delegate(Model d1) 
          { 
           mModel = d1; // mModel is a property defined in Window 
           Binding b = new Binding(); 
           b.Source = mModel; 
           MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); 
          }    
} 

また、バックグラウンドアクションを実行する前に、フィールド内のUIスレッドのディスパッチャを格納し、より良い制御のディスパッチャを使用する意図を示している可能性がありコードの: "私はこのコントロールが属しているスレッドに関係なく、これを呼び出す必要があります"。

更新:これはコントロールのインスタンスメソッドであることがわかりました。使用しているディスパッチャインスタンスは正しいものです。夜遅くに返事をするほど。また、あなたのコードはIEnumerableでモデルを置き換える私のために動作します。あなたのモデルに特別なものがありますか?

関連する問題