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

时间:2010-08-08 20:29:07

标签: mvvm system.reactive observable

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

var moves = Observable.FromEvent<MouseEventArgs>(frm, "MouseMove");

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

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

我完全不在赛道上吗?

3 个答案:

答案 0 :(得分:5)

以下是如何以MVVM方式实现Web服务字典的示例。它有三个部分:

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

    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);
        }
    }
    

    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>
    

答案 1 :(得分:1)

这可能会有所帮助:Reactive Extensions (Rx) + MVVM = ?

答案 2 :(得分:1)

执行键盘示例的最简单方法是将文本双向绑定到ViewModel的属性。然后,文本设置器可以写入私有Subject,其余代码将用作IObservable<string>的基础。从那里,您可以完成HOL样本。

鼠标移动通常被视为放置在ViewModel中的“视图”,但是如果它的逻辑足够复杂,您可以让它执行ICommand或者将逻辑放入行为中。如果 ICommand,您可以让该命令具有WhenExecuted IObservable属性,您可以在ViewModel中选择该属性。