如何在MVVM ViewModel中获取Rx Observable事件流

Ton*_*ony 2 mvvm system.reactive observable

我刚读Rx HOL NET.找到后(示例使用Windows窗体):

var moves = Observable.FromEvent<MouseEventArgs>(frm, "MouseMove");
Run Code Online (Sandbox Code Playgroud)

我想知道如何在一些WPF MVVM设置中实例化并传递对ViewModel的引用?根据我的理解,尝试在ViewModel中过滤此数据流是有意义的.

或者,如何为键盘输入TextBox做类似的事情?例如,在这种情况下,您不会将某些文本屏蔽行为附加到XAML中的控件,而是让VM中的Observer过滤并验证键盘输入.

我完全不在赛道上吗?

Mar*_*son 5

这里是你怎么一个例子可以实现在MVVM方式Web服务的字典.它有三个部分:

  1. ObservablePropertyBacking类,也是实现IObservable的属性(T)的支持
  2. MyViewModel类.它包含一个属性CurrentText,它使用ObservablePropertyBacking作为后备存储.它还会观察此属性的值,并使用它来调用字典Web服务.
  3. MainView.xaml包含一个TextBox.其Text属性与视图模型上的CurrentText属性双向绑定.

MyViewModel.cs:

class MyViewModel: INotifyPropertyChanged
{
    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string p)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(p));
    }

    #endregion

    public MyViewModel()
    {
        SetupProperties();
    }

    #region CurrentText

    /*  We use a special class for backing of the CurrentText property. This object
     *  holds the value of the property and also dispatches each change in an observable 
     *  sequence, i.e. it implements IObservable<T>.
     */
    private ObservablePropertyBacking<string> _textInput;
    public string CurrentText
    {
        get { return _textInput.Value; }
        set
        {
            if (value == _textInput.Value) { return; }
            _textInput.Value = value;
            RaisePropertyChanged("CurrentText");
        }
    }

    #endregion

    /*  Create property backing storage and subscribe UpdateDictionary to the observable 
        *  sequence. Since UpdateDictionary calls a web service, we throttle the sequence.
        */
    private void SetupProperties()
    {
        _textInput = new ObservablePropertyBacking<string>();
        _textInput.Throttle(TimeSpan.FromSeconds(1)).Subscribe(UpdateDictionary);
    }

    private void UpdateDictionary(string text)
    {
        Debug.WriteLine(text);
    }
}
Run Code Online (Sandbox Code Playgroud)

ObservablePropertyBacking.cs:

public class ObservablePropertyBacking<T> : IObservable<T>
{
    private Subject<T> _innerObservable = new Subject<T>();

    private T _value;
    public T Value
    {
        get { return _value; }
        set
        {
            _value = value;
            _innerObservable.OnNext(value);
        }
    }

    public IDisposable Subscribe(IObserver<T> observer)
    {
        return _innerObservable
            .DistinctUntilChanged()
            .AsObservable()
            .Subscribe(observer);
    }
}
Run Code Online (Sandbox Code Playgroud)

MainPage.xaml中:

  <Window 
    x:Class="RxMvvm_3435956.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
      <TextBox
        Text="{Binding CurrentText, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
  </Window>
Run Code Online (Sandbox Code Playgroud)