Обновление пользовательского интерфейса после привязки фоновых операций на ObservableCollection - PullRequest
0 голосов
/ 22 ноября 2011

У меня есть это:

  1. Показывает ожидающую анимацию, которая блокирует пользовательский интерфейс во время выполнения операции загрузки в фоновом режиме.
  2. В конце загрузки я вызываю метод, который создает пользовательский элемент управления и отображает некоторые данные с помощью привязок (и, среди прочего, ObservableCollection)
  3. Этот пользовательский элемент управления отображается, и пользователь может взаимодействовать с ним, однако набор ObservableCollection, похоже, застрял в другом потоке, поскольку не позволяет добавлять в него новые элементы.

Я пытался обновить пользовательский интерфейс при событии Completed BackgroundWorker, используя Dispatcher, используя DispatchTimer ... все это отображает пользовательский элемент управления, но ObservableCollection остается недоступным для добавления.

Код, который пытается добавить элементы в коллекцию, находится внутри UserControl.

Точная ошибка: « Этот тип CollectionView не поддерживает изменения в его SourceCollection из потока, отличного от потока Dispatcher "

Этого не произойдет, если я не выполняю загрузку в фоновом режиме.

Спасибо за любой обходной путь для этого.

Кстати, попытка добавить элементы с помощью Dispatcher также не работает.

Другими словами, я хотел бы создать объект в потоке пользовательского интерфейса, находясь в фоновом режиме ... Я знаю, что это может звучать глупо.

Ответы [ 5 ]

1 голос
/ 23 ноября 2011

Обычно я создаю объекты в своем потоке пользовательского интерфейса, а затем заполняю их данными, полученными из фонового потока.

Например,

void async LoadButton_Clicked(object sender, EventArgs e)
{
    MyCollection = new ObservableCollection<SomeItem>();

    // Can also use a BackgroundWorker
    var collectionData = await GetCollectionData();

    foreach(var item in collectionData)
    {
        MyCollection.Add(item);
    }
}

Я использую C # 5.0 async и await ключевые слова для асинхронных операций, но вы также можете использовать BackgroundWorker, который выполняет фоновую работу.

Вы также можете использовать Dispatcher.BeginInvoke() для более легкой фоновой работы (например, копирования данных вMyCollection), хотя для тяжелой работы я все еще блокирую пользовательский интерфейс, поэтому я предпочитаю использовать фоновые потоки.

1 голос
/ 23 ноября 2011

Возможно, вам придется проверить, какой Dispatcher вы используете? В вашем случае вы можете ссылаться на двух разных диспетчеров.

Также, почему бы не использовать потокобезопасную наблюдаемую коллекцию ?

0 голосов
/ 29 ноября 2011

Спасибо всем за вашу помощь ... парень из MS посетил компанию (извините за коммерческую аннотацию), чтобы заняться другими делами, я украл его и продемонстрировал это поведение.В течение 2 минут находит источник проблемы ... который я не совсем понимаю.

Бывает, что я использую ICollectionView для отображения отсортированной / отфильтрованной версии моей проблемнойObservableCollection.Я создавал этот ICollectionView в конструкторе моего класса, поэтому в момент десериализации он был создан в другом потоке.Он предложил перенести это создание в другое время в коде (когда будет прочитано соответствующее свойство).Это решило проблему.

Однако коллекция ObservableCollection, созданная в этом другом потоке, теперь позволяет мне добавлять новый элемент.Не знаю почему, но теперь это работает.

Извините за опоздание и еще раз спасибо.

0 голосов
/ 22 ноября 2011

Когда речь идет о потоках и элементах пользовательского интерфейса, одним из наиболее важных правил, которые могут в будущем избавить вас от многих проблем, является сохранение экземпляра пользовательского элемента в потоке пользовательского интерфейса.Конечно, вы можете справиться с этим.А если вам нужно изменить эти объекты из другого потока, вы можете использовать Диспетчер.

(ссылка на модель также может представлять интерес)

0 голосов
/ 22 ноября 2011

Невозможно изменить содержимое ObservableCollection в отдельном потоке, если представление связано с этой коллекцией, вместо этого вы можете переопределить ObservableCollection и обеспечить его поддержку и использовать его в своем приложении.

Этот образец содержит именно то, что вы хотите - http://tomlev2.wordpress.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

...