.net 观察添加到RX列表中的项目

.net 观察添加到RX列表中的项目,.net,system.reactive,.net,System.reactive,我试图让一个简单的演示工作 我有一个字符串集合,我想在不使用任何控制事件代码的情况下观察它的添加。不知何故,我得到的印象可能是错误的,Rx或.Net的另一部分支持这一点,而没有连接(可能或可能不)向集合添加成员的所有各种事件 如果我用一个间隔替换我的源代码,就像在注释掉的代码中一样,代理将被调用(ala,var source=Observable.interval(TimeSpan.FromSeconds(1));。这给了我希望,我可以在这里做我想做的事情,可能是错误的 基本的例子来自 在下面的

我试图让一个简单的演示工作

我有一个字符串集合,我想在不使用任何控制事件代码的情况下观察它的添加。不知何故,我得到的印象可能是错误的,Rx或.Net的另一部分支持这一点,而没有连接(可能或可能不)向集合添加成员的所有各种事件

如果我用一个间隔替换我的
源代码
,就像在注释掉的代码中一样,代理将被调用(ala,
var source=Observable.interval(TimeSpan.FromSeconds(1));
。这给了我希望,我可以在这里做我想做的事情,可能是错误的

基本的例子来自

在下面的代码中,我想做的是直接观察
source
集合(而不是通过控制事件),并在将项添加到集合时调用委托

如果LINQ或RX确实支持我的论点,即它们支持此功能,我宁愿不绕过LINQ或RX

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;

public class frmRx
{

    ObservableCollection<string> ObservableCollection = new ObservableCollection<string>();
    Dim source = Observable.ToObservable(ObservableCollection).ObserveOn(SynchronizationContext.Current)

    //this code worked, but it's not a collection I made
    //source = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => x.ToString).ObserveOn(SynchronizationContext.Current);

    private void frmRx_Load(System.Object sender, System.EventArgs e)
    {
        IConnectableObservable<string> Publication = Observable.Publish<string>(source);
        Publication.Subscribe(x => { AddToTreeView(x); }, ex => { }, () => { });
        Publication.Connect();
    }

    private void AddToTreeView(string Text)
    {
        TreeView1.Nodes.Add(Text); //this never gets called
    }

    // this is just my test way of adding a member to the collection.
    // but the adding could happen anywhere,
    // and I want to watch the collection changes regardless of how it came about
    private void TextBox1_TextChanged(System.Object sender, System.EventArgs e)
    {
        ObservableCollection.Add(TextBox1.Text.Last);
    }
    public frmRx()
    {
        Load += frmRx_Load;
       TextBox1.TextChanged += TextBox1_TextChanged;
        }
    }
使用Microsoft.VisualBasic;
使用制度;
使用系统集合;
使用System.Collections.Generic;
使用系统数据;
使用系统诊断;
使用System.Collections.ObjectModel;
使用System.Reactive.Linq;
使用系统、反应、主题;
使用系统线程;
公共类frmRx
{
ObservableCollection ObservableCollection=新的ObservableCollection();
Dim source=Observable.ToObservable(ObservableCollection).ObserveOn(SynchronizationContext.Current)
//这段代码很有效,但不是我收集的
//source=Observable.Interval(TimeSpan.FromSeconds(1))。选择(x=>x.ToString.ObserveOn(SynchronizationContext.Current);
私有void frmRx_加载(System.Object sender,System.EventArgs e)
{
IConnectableObservable Publication=Observable.Publish(来源);
Publication.Subscribe(x=>{AddToTreeView(x);},ex=>{},()=>{});
Publication.Connect();
}
私有void AddToTreeView(字符串文本)
{
TreeView1.Nodes.Add(Text);//这永远不会被调用
}
//这只是我向集合中添加成员的测试方法。
//但这种情况可能发生在任何地方,
//我想看收藏的变化,不管它是怎么发生的
私有void TextBox1\u TextChanged(System.Object sender,System.EventArgs e)
{
添加(TextBox1.Text.Last);
}
公共frmRx()
{
荷载+=frmRx_荷载;
TextBox1.TextChanged+=TextBox1\u TextChanged;
}
}

您犯了一个错误,即
可观察。ToObservable(ObservableCollection)
将创建一个
ioobservable
,它将为
可观察收集的未来更新生成值

事实并非如此

.ToObservable(…)
扩展方法简单地将
IEnumerable
转换为and
IOobservable
,以便在订阅可观察对象的时刻枚举值

如果希望将新值推送到订阅服务器,则需要使用
主题

除此之外,您的代码并没有尽可能简单。您为什么要胡闹着发布可观测数据

下面是您可以编写的最简单的代码,以使其正常工作:

public class frmRx
{
    private Subject<string> source = new Subject<string>();

    public frmRx()
    {
        source.ObserveOn(this).Subscribe(x => TreeView1.Nodes.Add(x));
        TextBox1.TextChanged += (s, e) => source.OnNext(TextBox1.Text);
    }
}
这避免了主题,并且在强类型时尽可能简单

最好更进一步,在结束时更好地清理订阅,如下所示:

        var subscription =
            Observable
                .FromEventPattern(
                    h => textBox1.TextChanged += h,
                    h => textBox1.TextChanged -= h)
                .Select(x => textBox1.Text)
                .Subscribe(x => treeView1.Nodes.Add(x));

        this.FormClosing += (s, e) => subscription.Dispose();

最简单的方法是使用Rx.net框架,如ReactiveUI。我将向您展示如何工作

ReactiveList<string> _collection = new ReactiveList<string>();

public Constructor()
{
     var subscription = _collection.ItemsAdded.Subject(added => doSomething(added));
     this.Disposed += (o, e) => subscription.Dispose();
}
ReactiveList _collection=new ReactiveList();
公共构造函数()
{
var subscription=_collection.ItemsAdded.Subject(added=>doSomething(added));
this.Disposed+=(o,e)=>subscription.Dispose();
}
在没有第三方的情况下,您需要多少代码才能使其“工作”。此外,此代码中根本没有异常处理

public class ViewModel
{
    private ObservableCollection<string> _source = new ObservableCollection<string>();

    public ViewModel()
    {
        //There will be issues with the exception handling
        Observable.FromEventPattern
            <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
            (x => _source.CollectionChanged += x, x => _source.CollectionChanged -= x)
            .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(x => x.EventArgs.NewItems.Cast<string>())
            .Subscribe(AddToTreeView);

    }

    public void AddToTreeView(string text)
    {
        TreeView1.Nodes.Add(text);
    }
}
公共类视图模型
{
私有ObservableCollection_source=新ObservableCollection();
公共视图模型()
{
//异常处理将出现问题
可观察的。从事件模式
(x=>\u source.CollectionChanged+=x,x=>\u source.CollectionChanged-=x)
.Where(x=>x.EventArgs.Action==NotifyCollectionChangedAction.Add)
.SelectMany(x=>x.EventArgs.NewItems.Cast())
.订阅(AddToTreeView);
}
公共void AddToTreeView(字符串文本)
{
TreeView1.Nodes.Add(文本);
}
}

首先回答你的“咆哮”。这些例子并不复杂。它们总是从简单开始,然后发展到更复杂的例子。你似乎在抱怨,为什么Rx.net如此复杂。原因很简单。因为它处理的是一个非常复杂的概念,时间。即Rx,同时处理时间的多个维度例如,一个常见的Rx“查询”是,“当用户停止键入500毫秒时,观察用户键入的内容,然后发送一个请求,我们将等待3秒钟,除非用户在请求期间再次开始键入,在这种情况下,取消。”现在还不清楚您想要的是什么
observateCollection
。问题的可悲事实是
observateCollection
尽管名称与Rx.net无关。您的问题是“如何让简单的sub/pub工作”但你永远不会说出你订阅/发布的内容。你的代码不会试图传达你想要做的事情。@Aron,请参阅注释掉的代码。我试图创建一个字符串列表,并在向该集合添加项目时激发委托。我想根据标题观察该集合。也许你可以撤消关闭vote now?谢谢。你的代码是错误的。如果它是可读的,它将是正确的。你仍然缺少很多信息。使用“修复我的代码”问题,你需要知道,代码应该用文字或伪代码做什么。
public class ViewModel
{
    private ObservableCollection<string> _source = new ObservableCollection<string>();

    public ViewModel()
    {
        //There will be issues with the exception handling
        Observable.FromEventPattern
            <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
            (x => _source.CollectionChanged += x, x => _source.CollectionChanged -= x)
            .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(x => x.EventArgs.NewItems.Cast<string>())
            .Subscribe(AddToTreeView);

    }

    public void AddToTreeView(string text)
    {
        TreeView1.Nodes.Add(text);
    }
}