DynamicData: сортировка связанного списка перезагружается при каждом изменении - PullRequest
0 голосов
/ 30 апреля 2018

Я использую превосходные dynamicdata для соединения моего уровня данных с моим пользовательским интерфейсом (используя RxUI). Динамическая часть данных сводится к следующему типичному коду. Существует SourceCache ItemViewModels ("_sourceCache"), который привязывается к ReactiveList ItemViewModels ("Models"), который в свою очередь (в представлении) связан как ListView.ItemsSource:

var propertyChanges = _sourceCache.Connect().WhenPropertyChanged(p => p.LastChange)
            .Throttle(TimeSpan.FromMilliseconds(250))
            .Select(_ => Unit.Default);

        var comparer = SortExpressionComparer<ItemViewModel>.Ascending(l => l.LastChange);

        _sourceCache.Connect()
            .Sort(comparer, propertyChanges)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(Models)
            .Subscribe();

(полный рабочий пример можно найти здесь )

При запуске примера весь список перезагружается видимым каждый раз, когда сортировка запускается изменением свойства (наблюдая за свойством LastChange). При выборе ListViewItem, часто выбор теряется, плюс видимая перезагрузка всего списка довольно отвлекает.

Мой вопрос сейчас такой: есть ли способ сортировки в моей цепочке DynamicData и без упомянутых проблем?

В идеале только измененные элементы будут менять свою позицию в списке, а остальные элементы будут оставаться видимыми.

Обновление

Спасибо Роланду за подсказку, но наблюдаемое поведение остается тем же, независимо от использования

Sort(comparer, propertyChanges)

или

AutoRefresh(m => m.LastChange)
.Sort(comparer)

Весь интерфейс List по-прежнему выглядит так, как будто он перезагружается (все элементы исчезают и появляются снова при каждом изменении). Как видно из моего связанного репозитория github, я случайным образом выбираю одну из связанных ItemViewModels и изменяю свойство «LastChanged». Может быть, это поведение UWP ListView?

Обновление 2

Такое же поведение можно увидеть, если я просто ReactiveList. Перемещать случайным образом один элемент каждые 1 сек, тем не менее весь список выглядит так, как будто он перезагружается каждый раз. Итак, я думаю это сам UWP ListView ...

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Обновление

Реализована новая операция для DynamicData, которая преобразует изменения «переместить» в «удалить по старому индексу» и «добавить по новому индексу», называемые TreatMovesAsRemoveAdd, для использования следующим образом:

_sourceCache.Connect()
        .Sort(comparer, propertyChanges)
        .TreatMovesAsRemoveAdd()
        .ObserveOn(RxApp.MainThreadScheduler)
        .Bind(Models)
        .Subscribe();

старый ответ:

Кажется, ListView не может обрабатывать (семантически) движущиеся объекты. просто добавь + удали. Поэтому я последовал совету Роланда и изменил SortedReactiveListAdaptor (скопировал его и изменил следующий метод:

    private void DoUpdate(IChangeSet<TObject, TKey> changes)
    {
        foreach (var change in changes)
        {
            switch (change.Reason)
            {
                case ChangeReason.Add:
                    _target.Insert(change.CurrentIndex, change.Current);
                    break;
                case ChangeReason.Remove:
                    _target.RemoveAt(change.CurrentIndex);
                    break;
                case ChangeReason.Moved:
                // ************************************** change from original ************************************************
                //_target.Move(change.PreviousIndex, change.CurrentIndex);
                //break;
                // ************************************** ******************** ************************************************
                case ChangeReason.Update:
                {
                    _target.RemoveAt(change.PreviousIndex);
                    _target.Insert(change.CurrentIndex, change.Current);
                }
                break;
            }
        }

    }

Так что все ходы будут рассматриваться как обновления (RemoteAt + Insert) Применение указанного SortedReactiveListAdaptor будет:

.Bind(new MovesToUpdatesReactiveListAdaptor<IItemViewModel, string>(Items))

вместо обычного

.Bind(Items)
0 голосов
/ 30 апреля 2018

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

Решение состоит в том, чтобы использовать AutoRefresh, который дает команду dd переоценивать отдельные элементы при изменении свойств.

.AutoRefresh(p=>p.LastChange).Sort(comparer)

Существует перегрузка для указания дросселя и планировщика.

...