Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 反应列表问题_C#_Reactive Programming_Reactiveui - Fatal编程技术网

C# 反应列表问题

C# 反应列表问题,c#,reactive-programming,reactiveui,C#,Reactive Programming,Reactiveui,我们对ReactiveUI比较陌生,所以这可以解释为什么我们在让视图模型工作时遇到一些问题 在我们的视图模型中,我们有一个类的ReactiveList,该类中有一个“selected” 在视图模型中,我们希望有一个“AnySelected”属性,这样,如果列表中至少有一个项目标记为selected,那么AnySelected为true 我们很难完成这项工作 作为一个仅使用字符串的小型测试应用程序,我们已经尝试了这一点,但是没有出现有关发生更改的消息 public class TestRx : R

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

在我们的视图模型中,我们有一个类的ReactiveList,该类中有一个“selected”

在视图模型中,我们希望有一个“AnySelected”属性,这样,如果列表中至少有一个项目标记为selected,那么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);
    }
}
公共类TestRx:ReactiveObject
{
私有反应列表mySelectedItems;
公共反应列表MySelectedItems
{
获取{return mySelectedItems;}
设置{this.RaiseAndSetIfChanged(ref mySelectedItems,value);}
}
公共TestRx()
{
var firstList=新的反应列表();
var t=此.whenyValue(x=>x.MySelectedItems);
var t1=t.Select(x=>x??新的反应列表());
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已更改{0}”,x==firstList));
Subscribe(z=>Debug.WriteLine(“t1已更改{0}”,z==firstList));
changed.Subscribe(x=>Debug.WriteLine(“changed:”);
Subscribe(x=>Debug.WriteLine(“itemChanged:”);
var replacementList=new ReactiveList(new[]{
新建SelItem(){Selected=false}
});
Debug.WriteLine(“分配第一个列表”);
MySelectedItems=firstList;
睡眠(100);
Debug.WriteLine(“*************************添加第2项列表”);
Add(“一个新字符串”);
//由于上述原因,我们没有收到任何调试消息
睡眠(100);
Debug.WriteLine(“******************************赋值null”);
MySelectedItems=null;
睡眠(100);
}
}

我们做错了什么?

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

  • 名单已经确定
  • 列表项会发生变化
  • 任何项目上的“选定”属性都会更改。请记住,您想要观看的项目会因为#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);
    
    IObservable when any为真(IEnumerable currentElements)
    {
    //注意:这里的“单位”指的是,我们不关心实际价值,只是
    //事情变了
    var NOTIFYWHENY SELECTEDITEMCHANGES=currentElements
    .Select(x=>x.wheny(y=>y.Selected,=>Unit.Default)。跳过(1))
    .Merge();
    返回notifyWhenAnySelectedItemChanges
    .StartWith(默认单位)
    .Select(=>currentElements.Any(x=>x.Selected));
    }
    //每当MySelectedItems发生更改或其中的项目发生更改时,
    //创建一个新的whenanytrue并切换到它
    当不可见时(x=>x.MySelectedItems.ItemsChanged)
    .Select(=>WhenAnyAreTrue(MySelectedItems))
    .Switch()
    .ToProperty(此,x=>x.AnySelected,out AnySelected);
    
    没有时间查看所有详细信息,但我对ReactiveList public ReactiveList MySelectedItems{get;private set;}使用此模式。ReactiveList是否有一个
    ChangeTrackingEnabled
    来帮助处理此场景?感谢您的回复,我正在慢慢地了解这一点。但这里有一些“边缘”情况:我看不到ItemsAnged,但有ItemsAdded和ItemsRemoved,但似乎没有ItemsReplaced(例如,在ReactiveList中的指定索引位置替换项目)。因此,我可以看到插入和删除的更改,但列表[2]=新建。。。样式替换。我是否遗漏了什么(itemschaging触发相同实例属性更改,但不触发列表替换)?根据RxUI的版本,这可能被称为“更改”我已经更新到最新的ReactiveUI预发布版本,并修改了您在上面所做的操作,以尝试适应MySelectedItems为null的情况,并将修改后的代码放在这里的摘要中。有没有什么方法可以用“较短的方式”来表达这一点?提前感谢您的指点。“RxUI的未来版本可以让事情变得更好”-这已经发生了吗?