2

I have custom control inherited from Textbox.

I want to make delay in calling textchanged event.

 Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
                handler => this.TextChanged += handler,
                handler => this.TextChanged -= handler
                ).Throttle(TimeSpan.FromMilliseconds(600))
                      .Where(e =>
                          {
                              var control= e.Sender as TextBox;
                              return control!= null && !string.IsNullOrEmpty(control.Text);
                          })

                      .Subscribe(x => Control_TextChanged(x.Sender, x.EventArgs));

Problem is it is giving error saying, cannot access Text property as current thread does not have access.

Can someone please advice?

Thanks, Vishal

4
  • Just a small comment - when using normal events you have to do var control= e.Sender as TextBox;, but you're using Rx and lambdas so this is still in scope. Your where-clause can be written as .Where(e => this != null && !string.IsNullOrEmpty(this.Text)). Commented Feb 3, 2016 at 7:00
  • And why are you calling off to Control_TextChanged? That seems to be a backwards step. Just put the code in the .Subscribe rather than in Control_TextChanged. Commented Feb 3, 2016 at 7:01
  • @Enigmativity another small comment :) We don't know if Control_TextChanged is called from somewhere else in the code. Or if the function length is 1000 lines. Point being: I think the implicit function call is better Commented Feb 3, 2016 at 8:36
  • 1
    @supertopi - We just don't know anything about it other than it is external to the current method. I try to use lambdas to encapsulate the code as encapsulation is one of the OO tenets so all things considered equal it's probably a good idea. Commented Feb 3, 2016 at 8:38

3 Answers 3

4

You can observe on UI thread:

Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
  handler => this.TextChanged += handler,
  handler => this.TextChanged -= handler)     
     .ObserveOn(DispatcherScheduler.Current)
     .Throttle(TimeSpan.FromMilliseconds(600))
     .Where(e =>
          {
              var control= e.Sender as TextBox;
              return control!= null && !string.IsNullOrEmpty(control.Text);
          })
     .Subscribe(x => Control_TextChanged(x.Sender, x.EventArgs));

Notice the use of DispatcherScheduler.Current it's in System.Reactive.Windows.Threading namespace in Rx-WPF NuGet package.

Sign up to request clarification or add additional context in comments.

Comments

3

You can use ObserveOnDispatcher extension method and have something like:

Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
                    ev => TextChanged += ev,
                    ev => TextChanged -= ev)
                          .Where(t => !string.IsNullOrEmpty(Text))
                          .Throttle(TimeSpan.FromMilliseconds(600))
                          .ObserveOnDispatcher()
                          .Subscribe(e => HandleTextChanged(e.EventArgs));

Comments

2

You will have to use Control.Invoke() to make changes to UI elements from any thread other than the main UI thread.

Where(e =>
    {
     var control= e.Sender as TextBox;

     return control != null 
          && !string.IsNullOrEmpty(Dispatcher.Invoke<string>(()=>  control.Text));

     })

4 Comments

where I can use, control.invoke. Could you pls give an example?
See updated code. Sorry if it's a bit messy. Doing this on my phone.
Ah the one you are saying is in Windows.Form. I am using WPF
I've never used WPF, but apparently the equivalent is to call Dispatcher.Invoke() - I have changed the answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.