2013-12-04 3 views
0

Мне было интересно, можно ли установить следующий сценарий с помощью RX?Заполнение ObservableCollection с использованием RX

У меня есть вызов службы REST, на которой располагается расстояние и загружает данные входных параметров, эти данные, чем вставленный в ObservableCollection из ViewModel, так что View покажет данные ... Псевдо код, как это:

public async Task<int> LoadData(int distance) 
{ 
    this.ListOnUI.Clear(); 
    var dataList = await Task.Run(() => _dataService.GetListAsync(distance)); 
    foreach(var dataItem in dataList) 
    { 
     this.ListOnUI.Add(dataItem); 
    } 
    return dataList.Count; 
} 

Теперь этот небольшой фрагмент кода завернут внутри метода, который возвращает подсчет списка данных. Что я делаю с этим подсчетом, проверьте, не возвращается ли сумма, равная 20, если не помню метод с большим расстоянием.

Так что не так с этой установкой ...

  1. Каждый раз, когда вызывается метод список UI очищается
  2. Пользователь иногда приходится долго ждать, пока мы не достигнем 20 пунктов
  3. В то время как мы не достигли 20 пунктов, пользовательский интерфейс будет действовать странно с расчетом списка

Так что мое чувство кишки говорит мне, что это можно решить, используя RX, так или иначе, чтобы мы «купили» загрузку/добавление список пользовательского интерфейса ,

Но мои знания о RX недостаточно хороши для его решения ... так что любые идеи?

Замечание: Когда мы вызываем службу LoadData, мы получаем строку JSON, которая затем отображается в коллекцию DataItems, поэтому, если мы не очистим пользовательский интерфейс ObservableCollection и просто добавим их с каждой итерацией ... мы получим тот же элемент несколько раз в списке, потому что это новые объекты (хотя и с теми же данными).

+0

Что конкретно представляет собой пользовательский интерфейс? Вы хотите заполнить список как можно скорее? Таким образом, если первый вызов возвращает 10 элементов, а второй вызов возвращает 20 с некоторым пересечением, тогда вы только изменяете список (добавление новых элементов и удаление их больше не присутствуют). Или что-то другое? Почему бы не вернуть список ('Задача >', когда у него есть 20 элементов и управлять вызовом внутри цикла в Задаче и заполнять пользовательский интерфейс с результатом? –

+0

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

+0

OK. Что такое подпись GetListAsync? Почему она завернута в Task.Run, если она уже асинхронна? Просто чтобы выйти из диспетчера? –

ответ

1

Есть ли ключ внутри объектов данных? Если это так, вы можете проверить свой foreach, если объект уже содержится, и добавьте его только в том случае, если это не так. Таким образом, вам не придется очищать его (вместе со всеми побочными эффектами).

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

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

+0

Правда, я мог видеть, есть ли что-то, что сделает каждый элемент данных уникальным, хотя Теперь мне интересно, как сделать добавление в ObservableCollection по-прежнему обеспечивать правильную сортировку? (Сортировка выполняется не по расстоянию, а по дате внутри элемента данных) – Depechie

1

Изменено для вычисления списка delta каждый раз. For содержит для корректной работы, вам просто нужно реализовать Equals соответствующим образом на возвращаемых элементах GetListAsync. Возможно, придуманное ключевое сравнение, предложенное SB Dev. Не уверен, что много Rx может привести к таблице в контексте вопроса.

public async Task<int> LoadData(int distance) 
    { 
     int count = 0; 
     IList<object> dataList = null; 
     while (count < 20) 
     { 
      dataList = await Task.Run(() => _dataService.GetListAsync(distance)); 
      count = dataList.Count; 
      var newItems = dataList.Except(ListOnUI).ToList(); 
      var removedItems = ListOnUI.Except(dataList).ToList();     
      removedItems.ForEach(x => ListOnUI.Remove(x)); 
      newItems.ForEach(ListOnUI.Add); 
     } 
     return count; 
    } 

Предполагая, что вы используете ObservableCollection для вашего списка, см Sort ObservableCollection - what is the best approach? для сортировки.

+0

Джеймс, это было то, что я делал но цикл While может занять много времени, если нам нужно увеличить расстояние много раз ... поэтому я хочу загружать элементы данных, когда они входят, не зависимо от итерации. SB Dev предложил добавить ключи ... – Depechie

+0

Отредактировано для учёта ваших комментариев. –

+0

Хорошо, позвольте мне подтвердить этот ответ, когда у меня есть время на этой неделе :) выглядит как хороший подход! – Depechie

0

Благодаря предлагаемым ответам, я подумал об использовании коллекции Sortable Observable и просто добавил элементы, когда они вошли!

Я использовал пример объяснена Andrea здесь: http://www.xamlplayground.org/post/2010/04/27/Keeping-an-ObservableCollection-sorted-with-a-method-override.aspx

Но используется двоичный параметр поиска отмечено в комментариях блога! Чтобы убедиться, что мы не останавливаем код, когда находим элементы, находящиеся в списке, я просто закомментировал исключение Throw.

Для этого мне нужно было только реализовать IComparable.

Смежные вопросы