Проблемы с реактивным списком

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

В нашей модели представления у нас есть ReactiveList класса, для которого в классе есть «выбранный».

В модели представления мы хотим иметь свойство AnySelected, чтобы если в списке есть хотя бы 1 элемент, помеченный как выбранный, то AnySelected имел значение true.

Мы испытываем трудности с получением этой работы.

В качестве небольшого тестового приложения, состоящего только из строк, мы попробовали это, но сообщения об изменениях не появляются.

public class TestRx : ReactiveObject
{
    private ReactiveList<string> mySelectedItems;

    public ReactiveList<string> MySelectedItems
    {
        get { return mySelectedItems; }
        set { this.RaiseAndSetIfChanged(ref mySelectedItems, value); }
    }

    public TestRx()
    {
        var firstList = new ReactiveList<string>();

        var t = this.WhenAnyValue(x => x.MySelectedItems);
        var t1 = t.Select(x => x ?? new ReactiveList<string>());

        var changed = t1.Select(x => x.Changed.Select(_ => Unit.Default));
        var itemChanged = t1.Select(x => x.ItemChanged.Select(_ => Unit.Default));
        var countChanged = t1.Select(x => x.CountChanged.Select(_ => Unit.Default));

        t.Subscribe(x => Debug.WriteLine("T HAS CHANGED {0}", x == firstList));
        t1.Subscribe(z => Debug.WriteLine("T1 Changed {0}", z == firstList));

        changed.Subscribe(x => Debug.WriteLine("Changed :"));
        itemChanged.Subscribe(x => Debug.WriteLine("Item Changed :"));

        var replacementList = new ReactiveList<SelItem>(new[] {
                new SelItem() { Selected = false } 
        });

        Debug.WriteLine("***********************Assign 1st list");
        MySelectedItems = firstList;
        Thread.Sleep(100);

        Debug.WriteLine("***********************Adding item 2 list");
        MySelectedItems.Add("a new string");
        // we don't get any debug messages  as a result of the above
        Thread.Sleep(100);

        Debug.WriteLine("***********************Assign null");
        MySelectedItems = null;
        Thread.Sleep(100);
    }
}

Что мы делаем не так ?


person jamie    schedule 04.06.2014    source источник
comment
нет времени рассматривать все детали, но я использую этот шаблон для ReactiveList‹› public ReactiveList‹string› MySelectedItems { get; частный набор; }   -  person kenny    schedule 04.06.2014


Ответы (1)


Это распространенный шаблон, но его немного сложно реализовать, потому что вам нужно обрабатывать все следующие сценарии:

  1. Список установлен
  2. Элементы списка меняются
  3. Свойство «Выбрано» для любых элементов изменяется. Имейте в виду, что элементы, которые вы хотите посмотреть, меняются из-за № 1 или № 2.

Как это сделать?

Вот один из способов сделать это. Это сложно, и это намекает на то, что будущие версии RxUI могут улучшить ситуацию, но вот что вы можете сделать сейчас.

IObservable<bool> WhenAnyAreTrue(IEnumerable<ViewModel> currentElements)
{
    // NB: 'Unit' here means, we don't care about the actual value, just
    // that something changed
    var notifyWhenAnySelectedItemChanges = currentElements
        .Select(x => x.WhenAny(y => y.Selected, _ => Unit.Default).Skip(1))
        .Merge();

    return notifyWhenAnySelectedItemChanges
        .StartWith(Unit.Default)
        .Select(_ => currentElements.Any(x => x.Selected));
}

// Any time MySelectedItems change or when the items in it change,
// create a new WhenAnyAreTrue and switch to it
this.WhenAnyObservable(x => x.MySelectedItems.ItemsChanged)
    .Select(_ => WhenAnyAreTrue(MySelectedItems))
    .Switch()
    .ToProperty(this, x => x.AnySelected, out anySelected);
person Ana Betts    schedule 04.06.2014
comment
Разве в ReactiveList нет ChangeTrackingEnabled, чтобы помочь с этим сценарием? - person Cameron MacFarland; 05.06.2014
comment
Спасибо за ответ, потихоньку разбираюсь с этим. Однако здесь есть несколько «пограничных» случаев: я не вижу ItemsChanged, но есть ItemsAdded и ItemsRemoved, но не появляется ItemsReplaced (например, заменить элементы в указанной позиции индекса в ReactiveList). Итак, я вижу изменения для вставок и удалений, но list[2] = new... замены стиля. Я что-то упустил (ItemsChanging срабатывает для тех же изменений свойств экземпляра, но не для замены списка)? - person jamie; 06.06.2014
comment
В зависимости от версии RxUI это может называться просто Changed - person Ana Betts; 07.06.2014
comment
Я обновил до последней предварительной версии ReactiveUI и изменил то, что вы сделали выше, чтобы попытаться приспособиться к тому, что MySelectedItems имеет значение null, и поместил измененный код в Gist здесь gist.github.com/jcmm33/2a297814a531d11cf89d . Есть ли способы представить это в «более короткой форме»? Заранее спасибо за любые указатели. - person jamie; 09.06.2014
comment
будущие версии RxUI могут улучшить ситуацию. Это уже произошло? - person Taylor Buchanan; 13.10.2016