DataGrid не обновляется, когда элементы добавляются в ObservableCollection в Silverlight - PullRequest
2 голосов
/ 18 августа 2011

У меня есть приложение Silverlight, которое взаимодействует со службой WCF.Он периодически получает новые элементы для добавления в список из этого сервиса, и каждый новый элемент добавляется в конец ObservableCollection (collection.Add () для каждого нового элемента).

Сами элементы неизменить, как только они будут получены, и класс элементов наследует INotifyPropertyChanged, однако, когда я добавляю новые элементы (полученные из WCF), DataGrid не обновляется.
Я также использую пользовательский форматировщик для привязки DataGrid, но яне думайте, что это проблема, поскольку начальный набор элементов отображается правильно (когда впервые установлен ItemsSource).

Я ожидал появления новых элементов, так как я подтвердил, что ObservableCollection испускаетправильное событие добавления.Так как ObservableCollection наследует от INotifyCollectionChanged, разве он не должен обновлять DataGrid?

Единственное решение, которое я нашел до сих пор, это:

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

Есть какие-нибудь идеи о том, как его обновить?Этот метод блокирует пользовательский интерфейс на заметное количество времени.
Спасибо

ОБНОВЛЕНИЕ: Код

Элементы раскрываются и извлекаются в событии обратного вызова 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), и события add запускаются, но на стороне пользовательского интерфейса ничего не происходит.

Обратные вызовы WCF могут происходить в другом потоке.

Ответы [ 2 ]

1 голос
/ 19 августа 2011

Я нашел решение!

Я реализовал методы Equals, GetHashCode и ToString в ItemWrapper и ExpandedTrade:

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 где-то проверял равенство, и что-то возвращало неверный тест. Идентификаторы уникальны, но с помощью стандартного теста на равенство теперь он работает.

0 голосов
/ 18 августа 2011

Скажите, если этот поток правильный:

  • DataGrid.ItemsSource == null;
  • [Update]
    • Создание новой наблюдаемой коллекции: CollectionA
    • Получить предметы и добавить их в коллекцию A
    • [Event]
      • DataGrid.ItemsSource == null -> ItemsSource = CollectionA
  • [Update]
    • Создание новой наблюдаемой коллекции: CollectionB
    • Получить предметы и добавить их в CollectionB
    • [Event]
      • DataGrid.ItemsSource! = Null -> Ничего не делать
  • => DataGrid.ItemsSource == CollectionA?

Или pastTrades - это поле, которое инициализируется только один раз? Скобки и границы методов помогут.

...