2011-08-18 150 views
2

我有一個與WCF服務交互的Silverlight應用程序。它定期接收新項目以添加到來自此服務的列表中,並且每個新元素都添加到每個新元素的ObservableCollection(collection.Add())的末尾。當項目添加到Silverlight中的ObservableCollection時,DataGrid不會更新

項目本身在收到後不會更改,並且項目的類繼承INotifyPropertyChanged,但是當我添加新項目(從WCF接收)時,DataGrid不會更新。
我也使用DataGrid綁定的自定義格式化程序,但我不認爲這是一個問題,因爲最初的一組項目顯示正確(當ItemsSource第一次設置時)。

我預料會出現新的元素,因爲我已確認ObservableCollection發出了正確的添加事件。由於ObservableCollection繼承自INotifyCollectionChanged,它不應該更新DataGrid嗎?

到目前爲止,我發現的唯一的解決辦法是:

dataGrid.ItemsSource = null; 
dataGrid.ItemsSource = collection; 

如何把它更新任何想法?這種方法阻止了用戶界面的時間。
感謝

UPDATE:代碼

的元素在WCF回調事件擴大和提取:

// The ItemWrapper allows the Binding converter to be passed the entire trade object, rather than just each property. 
ObservableCollection<ItemWrapper<ExpandedTrade>> pastTrades = new ObservableCollection<ItemWrapper<ExpandedTrade>>(); 
.... 

     // Extract and expand data - MinimalTrade is the data sent through WCF 
     var convertedTrades = from MinimalTrade t in e.trades 
            select new ItemWrapper<ExpandedTrade>(
             new ExpandedTrade(t, 
              usernames.ContainsKey(t.UserToId) ? usernames[t.UserToId] : null, potentialWealth != null ? potentialWealth.CurrentWealth : null)); // Get name, otherwise null. 
     // Data now expanded (to show full information like usernames 
     // pastTrades is an observableCollection 
      foreach (var trade in convertedTrades) 
      { 
       pastTrades.Add(trade); 
      } 
      OnNewMyTradeHistory(pastTrades); 

的OnNewMyTradeHistory事件再做到這一點:

if (tradeHistory.ItemsSource == null) tradeHistory.ItemsSource = trades; 

這隻套ItemsSource曾經(到ObservableCollection)和添加事件觸發,但沒有發生在用戶界面上。

WCF回調可能發生在另一個線程中。

+0

您是否綁定到依賴項屬性? –

+1

這應該工作。你將不得不向我們展示更多的代碼。你如何添加項目到你的收藏?你能提供一個你可以在這裏完整提供的問題的非常精簡的版本嗎? – ColinE

+0

您是否正在更新後臺線程上的數據網格源?我有問題讓PropertyChanged事件在使用一些後臺線程時正確觸發 – Rachel

回答

1

我找到了解決方案!

我實現了兩個ItemWrapper和ExpandedTrade的EqualsGetHashCodeToString方法:

ItemWrapper.cs:(調用在子類中的等效方法)

public override bool Equals(object obj) 
    { 
     if(obj is T) return Quote.Equals(obj); 
     if (obj is ItemWrapper<T>) return Quote.Equals(((ItemWrapper<T>)obj).Quote); 
     return this == obj; 
    } 
    public override int GetHashCode() { return Quote.GetHashCode(); } 
    public override string ToString() { return Quote.ToString(); } 

ExpandedTrade.cs:

public override bool Equals(object obj) 
    { 
     if (obj == null) return false; 
     ExpandedQuote q = obj as ExpandedQuote; 
     if (q == null) return false; 
     return q.Id == Id; 
    } 

    public override int GetHashCode() { return Id; } 

刪除這些方法後,它工作。我可以想象DataGrid在某處測試是否相等,並且某種方式返回了不正確的測試。這些ID是唯一的,但通過使用引用相等的默認測試,它現在可以工作。

0

告訴我,如果這個流程是正確的:

  • DataGrid.ItemsSource == NULL;
  • [更新]
    • 創建新觀察到的集合:CollectionA
    • 獲取項目,並把它們添加到CollectionA
    • [事件]
      • DataGrid.ItemsSource == NULL - >的ItemsSource = CollectionA
  • [更新]
    • 創建新觀察到的集合:CollectionB
    • 獲取項目,並把它們添加到CollectionB
    • [事件]
      • DataGrid.ItemsSource!= NULL - >什麼都不做
  • => DataGrid.ItemsSource == CollectionA?

或者pastTrades是隻初始化一次的字段?括號和方法邊界將有所幫助。

+0

CollectionA _is_'pastTrades',並且僅被初始化一次。所有新元素都添加到'pastTrades'。 'pastTrades'是在構造函數中創建的。我也可以通過使用調試器確認這個工作正常。如果我在Locals窗口中查看tradeHistory.ItemsSource(添加了10個以上項目後),我可以看到這10個新項目已進入ObservableCollection(即ItemsSource)。調試器顯示〜15個元素,但DataGrid只顯示最初的〜5。 – neuropie

+0

@neuropie:現在** **確實應該工作。你能上傳一個可靠地證明問題的項目嗎?所有的上下文可能都需要這個... –

相關問題