12

IObservable<T>&IObserver<T>はオブザーバー パターンの実装であり、.Net イベントと同様の状況で使用できることを理解しています。

と何か関係があるのか​​なINotifyPropertyChanged

現在INotifyPropertyChanged、winforms と WPF アプリケーションでデータ バインディングに使用していますが、UI データ バインディング シナリオで IObservable を使用できるかどうか疑問に思っていましたか?

乾杯

AWC

4

6 に答える 6

5

私が収集できる限り、関係はありません。オブザーバー/.NET イベンティングは、オブザーバー/通知スタイルの動作を実現する 2 つの方法です。

Microsoft の答えは、手動で登録された Observer オブジェクトを支持して .NET イベント パターンを非推奨にするのではなく、.NET イベント パターンの上に構築することでした。

イベントに関する私の最大の不満の 1 つは、オンデマンドでデリゲート チェーンをクリアできないことです。これにより、かなりの数のマネージ メモリ リーク シナリオが発生します。この目的のために、Microsoft は弱いイベントの概念を導入しました。つまり、Observables/Observer のタイムラインの不一致の問題に対処するためです。

WeakEvent パターンの詳細については、こちらを参照してください。

Josh Smith は、INotifyPropertyChanged の WeakEventManager の実装をリリースしました。これにより、プロパティを変更するオブジェクトとそのオブザーバーを接続する (メモリの観点から) より安全な方法が提供されます。

于 2010-02-08T23:49:35.273 に答える
3

WinForms と WPF バインディングも をサポートしない限りIObservable、モデルの変更で UI を更新し続けることは役に立ちません。使用できる理由INotifyPropertyChangedは、WinForms と WPF のバインド コードがこのインターフェイスを探し、実装時にそのイベントを使用して UI を最新の状態に保つためです。

于 2010-01-29T17:22:32.333 に答える
2

First off, I'm a bit new to Rx, so take my comments accordingly.

That said, I think that there is a great opportunity for cooperation between INotifyPropertyChanged and Rx's IObservable. I think it's relatively obvious that the UI is built around INPC at this point. However, INPC is also a primary way of detecting changes and managing scenarios where a domain model or view model has interdependencies between objects and properties. It is these interdependencies that seem like good candidates for Rx.

Working with INPC directly is a bit tricky and somewhat painful. Lots of magic strings to deal with. It is also a bit painful to watch for an event on an object multiple levels away in the object tree.

But if I can model these interactions "reactively", then my view models and domain models start to feel a bit more elegant. This is evident in the elegance of projects like Bindable Linq, Continuous Linq, Obtics, etc. These libraries make it simple to create "live values" or "live collections" that update automatically (dare I say "reactively") to changes. Continuous Linq even has a "reactive object" framework to do reactive programming, albeit without Rx.

It seems to me that the synergies come in if we can use Rx to keep the model and view model coherent. Then we can make the "bindable surface" of the model / view model honor the INPC by continuing to raise PropertyChanged as needed. I've seen a couple elegant extension methods that will create an observable from INotifyPropertyChanged. It seems that the other half of this might be to create some infrastructure that translates from Rx back to INPC.

于 2010-06-18T16:36:14.777 に答える
1

Rx 拡張機能で定義されている IObserver/IObservable を意味する場合:

http://channel9.msdn.com/shows/Going+Deep/Kim-Hamilton-and-Wes-Dyer-Inside-NET-Rx-and-IObservableIObserver-in-the-BCL-VS-2010/

と:

http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

それからリンゴとオレンジのようです。

INotifyPropertyChanged は、バインドされた値をいつ更新するかをコントロールに知らせるために、databinding/etc に共通のイベント フックアップを提供するだけです。

IObservable/IObserver は「一連のイベントでクエリを実行する」ことに似ていますが、それでさえ不十分な説明です。

うーん...わかりました、コレクションと呼ばれるこの「バッグ」に物を入れて、そのコレクションに (手動または LINQ ステートメントを使用して) クエリを実行して値を引き出す方法を知っていますよね? そのようなものですが、「バッグ」からデータを「引き出す」のではなく、イベントを「プッシュ」します。

役立つか、さらに混乱させる可能性のある恥知らずなプラグイン: http://blog.lab49.com/archives/3252

于 2010-02-16T20:41:41.413 に答える
0

多くの場合、MVVM で提示する最も簡単な方法IObservable<T>は、以下のような従来のビューモデル オブジェクトを作成し、手動でオブザーバブルにサブスクライブすることです。サブスクリプションは.ObserveOn(SynchronizationContext.Current)、UI スレッドですべての通知をディスパッチするために使用して実行する必要があります。次に、その時点で同期コンテキストが存在する必要があります ( SynchronizationContext.Currentis null before new Application().Run(mainWindow))。以下のサンプルを参照してください。

public class ViewModel : INotifyPropertyChanged
{
    private int _property1;

    public int Property1
    {
        get => _property1;
        set
        {
            _property1 = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Property1)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

景色:

<Window x:Class="ConsoleApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TextBox Text="{Binding Property1}" />
</Window>

呼び出し元メソッド:

[STAThread]
static void Main()
{
    var model = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)).Take(10);
    var viewModel = new ViewModel();
    var mainWindow = new MainWindow
    {
        DataContext = viewModel
    };
    IDisposable subscription = null;

    mainWindow.Loaded += (sender, e) =>
        subscription = model
            .ObserveOn(SynchronizationContext.Current) // Dispatch all the events in the UI thread
            .Subscribe(item => viewModel.Property1 = item);

    new Application().Run(mainWindow);

    subscription?.Dispose();
}

アップデート

もう 1 つのオプションは、ReactiveUI.WPFとさらに簡潔なReactiveUI.Fodyを使用して、ビューモデルで自動プロパティを生成することです。

ビューモデル:

public class ViewModel : ReactiveObject, IDisposable
{
    private readonly IDisposable subscription;

    public ViewModel(IObservable<long> source)
    {
        subscription = source
            .ObserveOnDispatcher()
            .ToPropertyEx(this, x => x.Property1);
    }

    // To be weaved by Fody
    public extern long Property1 { [ObservableAsProperty]get; }

    // Unsubscribe from the source observable
    public void Dispose() => subscription.Dispose();
}

ここでObserveOnDispatcher()の呼び出しは、ディスパッチャーが開始されておらず、SynchronizationContext.Currentnull の場合でも機能します。呼び出し元メソッド:

[STAThread]
static void Main()
{
    new Application().Run(
        new MainWindow
        {
            DataContext = new ViewModel(
                Observable.Timer(
                    TimeSpan.Zero,
                    TimeSpan.FromSeconds(1))
                .Take(20))
        });
}

ソリューション ファイルの近くにある FodyWeavers.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
    <ReactiveUI />
</Weavers>
于 2018-12-31T07:11:15.650 に答える