.NET中的响应式扩展(Rx)在WPF-MVVM中的应用

12
我将使用Reactive extensions for NET (Rx)与Caliburn.Micro在我的WPF应用程序中。我正在尝试将我的WPF应用程序移植到使用MVVM架构,并且需要监视TextBox控件的Text属性更改。
如果Text属性的上次更改时间超过3秒钟,我需要调用服务的LoadUser方法。
将逻辑从旧解决方案迁移到新的MVVM架构解决方案中。

OLD

XAML:

<TextBox Name="Nick" 
         Grid.Row="0"
         FontSize="14"
         Margin="2,2,2,2" 
         HorizontalAlignment="Stretch" 
         TextChanged="Nick_TextChanged" />

代码后台,我有以下内容:
...

Observable.FromEvent<TextChangedEventArgs>(Nick, "TextChanged")
          .Select(e => ((TextBox)e.Sender).Text)
          .Where(text => text.Length > 3)               
          .Do(LoadUser)     
          .Throttle(TimeSpan.FromSeconds(3000))     
          .Subscribe(LoadUser);

...
private  void LoadUser(string text){...}

我想在我的视图模型类中使用Observable.FromEvent。类似这样的东西

WPF与MVVM

视图:

<TextBox Name="Nick" 
         Grid.Row="0"
         FontSize="14"
         Margin="2,2,2,2" 
         HorizontalAlignment="Stretch"
         Micro:Message.Attach="[TextChanged]=[Action TextChanged()]"/>

视图模型:

[Export(typeof(IAddFriendViewModel))]
public class AddFriendViewModel : Screen, IAddFriendViewModel
{
    private string _nick;

    public string Nick
    {
        get { return _nick; }
        set
        {
            _nick = value;
            NotifyOfPropertyChange(()=>Nick);
        }
    }

    ...

    //how can I access to textbox control Nick in view from view model class?
    Observable.FromEvent<TextChangedEventArgs>(Nick, "TextChanged")
              .Select(e => ((TextBox)e.Sender).Text)
              .Where(text => text.Length > 3)
              .Do(LoadUser)
              .Throttle(TimeSpan.FromSeconds(3000))
              .Subscribe(LoadUser);
    ...

    private void LoadUser(string text)
    { }

    public void TextChanged()
    {
    }
}

我的问题是Observable.FromEvent使用了TextBox控件,我不知道如何从我的ViewModel类中访问这个控件。

我可以绑定到TextBox的Text属性,或者将一个命令绑定到TextBox控件的某个事件上,但是这种方法使用了视图中的对象。

谢谢提供思路。


这并没有真正回答问题,但我建议你看一下 ReactiveUI。所有你需要的东西都已经在那里实现了。 - ionoy
1个回答

27

在您的ViewModel中添加一个Nick属性并实现INotifyPropertyChanged。然后你就可以这样做:

Observable.FromEventPattern<PropertyChangedEventArgs>(this, "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "Nick")
          .Select(_ => this.Nick)
          .Where(text => text.Length > 3)
          //Subscribe will call LoadUser, no need for the extra Do(...)
          .Throttle(TimeSpan.FromSeconds(3000))
          .Subscribe(LoadUser);  

然后您的XAML将类似于以下内容

<TextBox Name="Nick" 
         Grid.Row="0"
         FontSize="14"
         Margin="2,2,2,2" 
         HorizontalAlignment="Stretch"
         Text="{Binding Nick, UpdateSourceTrigger=PropertyChanged}" />

9
在上面的代码中,注意FromEvent现在变成了FromEventPattern(FromEvent需要显式连接)。 - Lex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接