15

As a proof of concept, I want to write "Done" in a text box after a check box has been checked and a key has been pressed in a text box (in either order). I would expect this code to handle this, but it writes Done as soon as either event happens. Thanks for your help.

var seq = Observable.FromEvent<EventArgs>(this.checkBox, "CheckedChanged")
   .Merge(Observable.FromEvent<KeyPressEventArgs>(this.textBox, "KeyPress"));

seq.Subscribe((unused) => this.resultTextBox.Text = "Done");
Marcel Lamothe
  • 12,452
  • 9
  • 34
  • 44

2 Answers2

25

You can use Observable.When like so (I've added an additional CheckBox for this example):

var checkChanged  = Observable.FromEvent<EventArgs>(this.checkBox, "CheckedChanged");
var check1Changed = Observable.FromEvent<EventArgs>(this.checkBox1, "CheckedChanged");
var keyPress      = Observable.FromEvent<KeyPressEventArgs>(this.textBox, "KeyPress");

var plan1 = checkChanged
            .And(check1Changed).And(keyPress)
            .Then((cc, cc1, kp) => "Done.");

var when = Observable.When(plan1);

when.Subscribe((result) => this.resultTextBox.Text = result);

Also, if you can join other plans together, for example if things can be "done" when either one set of events fire, or also when another set of events fire:

var checkChanged  = Observable.FromEvent<EventArgs>(this.checkBox, "CheckedChanged");
var check1Changed = Observable.FromEvent<EventArgs>(this.checkBox1, "CheckedChanged");
var keyPress      = Observable.FromEvent<KeyPressEventArgs>(this.textBox, "KeyPress");
var keyPress1     = Observable.FromEvent<KeyPressEventArgs>(this.textBox1, "KeyPress");

var plan1 = checkChanged.And(check1Changed).And(keyPress).Then((cc, cc1, kp) => "Done.");
var plan2 = keyPress.And(keyPress1).Then((kp, kp1) => "Alternate done.");

var join = Observable.When(plan1, plan2);
Richard Anthony Hein
  • 10,550
  • 3
  • 42
  • 62
1

if you need both events to happen - consider using Zip. Merge will trigger the event if any of merged sources raise it.

desco
  • 16,642
  • 1
  • 45
  • 56