当项目添加到Silverlight中的ObservableCollection时,DataGrid不会更新

时间:2011-08-18 12:04:52

标签: c# silverlight datagrid observablecollection

我有一个与WCF服务交互的Silverlight应用程序。它会定期接收要添加到此服务列表中的新项目,并将每个新元素添加到ObservableCollection的末尾(每个新元素的collection.Add())。

项目本身在收到后不会更改,并且项目的类继承INotifyPropertyChanged,但是当我添加新项目(从WCF收到)时,DataGrid不会更新。
我也在为DataGrid绑定使用自定义格式化程序,但我不认为这是一个问题,因为初始项目集正确显示(首次设置ItemsSource时)。

我原本期望出现新元素,因为我已经确认ObservableCollection正在发出正确的add事件。由于ObservableCollection继承自INotifyCollectionChanged,它不应该更新DataGrid吗?

到目前为止我找到的唯一解决方案是:

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

有关如何更新的任何想法?此方法会阻止UI显着的时间量 感谢

更新:代码

在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)并且添加事件正在触发,但UI端没有任何事情发生。

WCF回调可能发生在另一个线程中。

2 个答案:

答案 0 :(得分: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是唯一的,但是通过引用使用相等的默认测试,它现在可以工作。

答案 1 :(得分:0)

告诉我这个流程是否正确:

  • DataGrid.ItemsSource == null;
  • [更新]
    • 创建新的可观察集合:CollectionA
    • 获取项目并将其添加到CollectionA
    • [事件]
      • DataGrid.ItemsSource == null - &gt; ItemsSource = CollectionA
  • [更新]
    • 创建新的可观察集合:CollectionB
    • 获取项目并将其添加到CollectionB
    • [事件]
      • DataGrid.ItemsSource!= null - &gt;什么都不做
  • =&GT; DataGrid.ItemsSource == CollectionA?

或者是pastTrades一个只初始化一次的字段?括号和方法边界会有所帮助。