ReactiveList问题

时间:2014-06-04 17:44:45

标签: c# reactive-programming reactiveui

我们对ReactiveUI比较新,所以这可以解释为什么我们在使视图模型工作时遇到一些问题。

在我们的视图模型中,我们有一个类的ReactiveList,在类中有一个'selected'。

在视图模型中,我们希望有一个'AnySelected'属性,如果列表中至少有一个项目标记为选中,则AnySelected为真。

我们很难完成这项工作。

作为一个小型测试应用程序,只有字符串,我们已经尝试过,但不会出现有关更改的消息。

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);
    }
}

我们做错了什么?

1 个答案:

答案 0 :(得分:3)

这是一种常见模式,但实施起来有点棘手,因为您必须处理以下所有情况:

  1. 列表已设置
  2. 列表项目更改
  3. &#34;选择&#34;任何物品的财产变更。请记住,您要观看的项目会因#1或#2而发生变化。
  4. 我该怎么做?

    这是一种方法。这很复杂,这暗示了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);