2009-07-25 118 views
2

在我的Window構造函數InitializeComponents後,我需要創建一個對象並將其綁定到一個數據網格。由於創建對象花費的時間太多,所以窗口需要一段時間才能顯示出來。所以我決定將對象的創建移動到後臺線程,並通過執行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委託中。但我仍然很好奇爲什麼上面的代碼沒有。

回答

0

我會建議另一種方法。

不應該從代碼調用綁定,而應該在XAML中定義它。

您可以在窗口上添加一個類型爲Model的DependencyProperty,並將其稱爲「CurrentModel」並將其初始值設置爲NULL。看起來你已經有一個名爲mModel的屬性,那是DependencyProperty?

您可以定義CurrentModel的綁定到DataGrid或XAML中的哪個控件。

而在委託結束時,Dispatcher.Invoke應該只設置CurrentModel,綁定將自動完成。

+0

我曾嘗試過這種不在xaml中,但只是設置綁定到屬性,屬性爲null。所以代表只有一行mModel = d1。但沒有發生。它不是一個依賴屬性,而是一個實現notifypropertychanged的普通屬性。 – Sharun 2009-07-25 13:06:47

0

調用哪個調度程序實例Invoke

我猜這是來自執行CreateModel的後臺線程的調度程序,而不是來自UI線程的調度程序。

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替換您的模型。你的模型中有什麼特別的東西?

相關問題