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

tod*_*dmo 2 .net system.reactive

我想要一个简单的演示工作.

我有一个字符串集合,我想看它添加,而不使用任何控制事件代码.不知怎的,我得到的印象,或许是错误的,Rx或.Net的另一部分支持这一点,而不是诉诸所有各种事件(可能会或可能不会)将成员添加到集合中.

如果我source用一个间隔替换我,就像在注释掉的代码中一样,委托被调用(ala,.var source = Observable.Interval(TimeSpan.FromSeconds(1));这让我希望我可以做我想做的事,也许是错误的.

基本示例来自创建和订阅简单可观察序列

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

我宁愿不绕过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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Eni*_*ity 8

你犯的错误Observable.ToObservable(ObservableCollection)会产生一个IObservable<string>会产生未来更新价值的错误ObservableCollection.

它不是.

.ToObservable(...)扩展方法只是简单地将一个IEnumerable<>进入并IObservable<>使得所述值在时间可观察到的订阅了的时刻计数.

Subject<string>如果您希望将新值推送给订阅者,则需要使用a .

除此之外,您的代码也不尽如人意.你为什么要发布可观察量?

以下是您可以编写的最简单的代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经把.ObserveOn(this)它包括在内,因为这是一个好习惯,但在这种情况下不应该需要它.

我希望看到的是:

public class frmRx
{
    public frmRx()
    {
        Observable
            .FromEventPattern(
                h => textBox1.TextChanged += h,
                h => textBox1.TextChanged -= h)
            .Select(x => textBox1.Text)
            .Subscribe(x => treeView1.Nodes.Add(x));
    }
}
Run Code Online (Sandbox Code Playgroud)

这避免了主题,并且它在强类型时可以获得简单.

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

        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();
Run Code Online (Sandbox Code Playgroud)


Aro*_*ron 1

最简单的方法是使用 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();
}
Run Code Online (Sandbox Code Playgroud)

这里需要多少代码才能使其在没有第三方的情况下“工作”。另外,这段代码根本没有异常处理。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)