Reactive Extensions for .NET (Rx) in WPF - MVVM

Jan 3, 2011 at 5:51 PM

I would like use observer on textbox control in view. If the last change of the Text property was more than 3 seconds ago I need to call the LoadUser method of a service.

Nick property is bind on textbox control.

 

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

.....

            Observable.FromEvent<PropertyChangedEventArgs>(this, "PropertyChanged")
                      .Where(e => e.EventArgs.PropertyName == "Nick")
                      .Select(_ => this.Nick)
                      .Where(text => text.Length > 3)
                      .Throttle(TimeSpan.FromSeconds(3000))
                      .Subscribe(LoadUser);

...


        private void LoadUser(string nick)
       {}

My problem is that observer use PropertyChanged method. Caliburn use on notification NotifyOfPropertyChane method.

 

First  try this:

 

            Observable.FromEvent<PropertyChangedEventArgs>(this, "NotifyOfPropertyChange")
                      .Where(e => e.EventArgs.PropertyName == "Nick")
                      .Select(_ => this.Nick)
                      .Where(text => text.Length > 3)
                      .Throttle(TimeSpan.FromSeconds(3000))
                      .Subscribe(LoadUser);

But it is  stupidity. What is correct way for caliburn micro?

Coordinator
Jan 3, 2011 at 5:59 PM

I don't have much experience with Rx, but maybe you could create a custom event for that one property and raise it in the setter (in addition to NotifyOfPropertyChange), then use Observable to track your custom event.

Jan 3, 2011 at 6:29 PM

My temporary solution is :

    [Export(typeof(IAddFriendViewModel))]
    public class AddFriendViewModel : Screen, IAddFriendViewModel, INotifyPropertyChanged
    {
        public new event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        public string Nick
        {
            get { return _nick; }
            set
            {
                _nick = value;
                NotifyPropertyChanged("Nick");
                //NotifyOfPropertyChange(() => Nick);
            }
        }

...

            Observable.FromEvent(this, "PropertyChanged")
                      .Where(e => e.EventArgs.PropertyName == "Nick")
                      .Select(_ => this.Nick)
                      .Where(text => text.Length > 3)
                      .Do(LoadUser)
                      .Throttle(TimeSpan.FromSeconds(3000))
                      .Subscribe(LoadUser);
}

Jun 30, 2013 at 4:39 PM
This is an old thread, but I found the following to work great:

var observable = Observable.FromEventPattern<PropertyChangedEventArgs>(this, "PropertyChanged");
observable.Where(e=> e.EventArgs.PropertyName == "SearchText").Throttle(TimeSpan.FromSeconds(.5)).Subscribe(e => Search());
Jul 4, 2013 at 4:59 AM
Edited Jul 4, 2013 at 4:59 AM
Aside what gregoryagu suggested you could also use Delayed Binding attribute starting with WPF 4.5

<TextBlock Text="{Binding Name, Delay=3000}"/> with these you do not need to do this extra workarounds

Thanks,
Rohit
http://rohiton.net