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

发布于 2024-11-30 08:55:16 字数 1919 浏览 1 评论 0原文

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

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

我本来希望出现新元素,因为我已经确认 ObservableCollection 正在发出正确的添加事件。既然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 回调可能发生在另一个线程中。

I have a Silverlight application which interacts with a WCF service. It periodically receives new items to add to a list from this service, and each new element is added to the end of an ObservableCollection (collection.Add() for each new element).

The items themselves don't change once they are received, and the items' class inherits INotifyPropertyChanged, however when I add new items (received from WCF), the DataGrid doesn't update.
I am also using a custom formatter for the DataGrid binding, but I don't think this is a problem as the initial set of items appear correctly (when the ItemsSource is first set).

I would have expected the new elements to appear, as I have confirmed that the ObservableCollection is emitting the correct add event. Since ObservableCollection inherits from INotifyCollectionChanged, shouldn't it update the DataGrid?

The only solution I have found so far is:

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

Any ideas on how to get it updating? This method blocks the UI for a noticable amount of time.
Thanks

UPDATE: Code

The elements are expanded and extracted in the WCF callback event:

// 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);

The OnNewMyTradeHistory event then does this:

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

This only sets ItemsSource once (to the ObservableCollection) and the add events are firing, but nothing is happening on the UI side.

The WCF callbacks might be happening in another thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等往事风中吹 2024-12-07 08:55:16

我找到了解决方案!

我已经在 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 是唯一的,但通过使用默认的引用相等测试,它现在可以工作。

I found the solution!

I had implemented the Equals, GetHashCode and ToString methods in both ItemWrapper and ExpandedTrade:

ItemWrapper.cs: (Calls the equivalent methods in the child class)

    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; }

After removing these methods, it worked. I'd imagine that the DataGrid was testing for equality somewhere, and somehow something was returning an incorrect test. The IDs are unique, but by using the default test of equality by reference, it now works.

茶色山野 2024-12-07 08:55:16

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

  • DataGrid.ItemsSource == null;
  • [更新]
    • 创建新的可观察集合:CollectionA
    • 获取项目并将其添加到 CollectionA
    • [活动]
      • DataGrid.ItemsSource == null -> ItemsSource = 集合A
  • [更新]
    • 创建新的可观察集合:CollectionB
    • 获取项目并将其添加到 CollectionB
    • [活动]
      • DataGrid.ItemsSource!= null ->什么也不做
  • => DataGrid.ItemsSource == CollectionA?

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

Tell me if this flow is correct:

  • DataGrid.ItemsSource == null;
  • [Update]
    • Create new observable collection: CollectionA
    • Get items and add them to CollectionA
    • [Event]
      • DataGrid.ItemsSource == null -> ItemsSource = CollectionA
  • [Update]
    • Create new observable collection: CollectionB
    • Get items and add them to CollectionB
    • [Event]
      • DataGrid.ItemsSource != null -> Do Nothing
  • => DataGrid.ItemsSource == CollectionA?

Or is pastTrades a field which is only initialized once? Brackets and method boundaries would help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文