2010-03-11 73 views
1

我在Silverlight应用程序中启用了2个触摸Canvas。我需要做的是当一个人持有(按下并持续按下)两个画布同时在屏幕上增加一次数值。这应该发生在每个“双倍”持有。我可以使用普通事件做到这一点,但尝试使用RX编写相同的事情,我陷入困境。在RX中组合多个事件

目前我的代码看起来与独立事件方法(使用全局变量和全局方法)完全相同,但我认为必须有更好的方式来编写它。任何人都可以提出更好的方法?

 var leftHold = Observable.FromEvent<TCanvas.HoldHandler, GestureHoldEventArgs>(
       h => new TCanvas.HoldHandler(h), 
       h => HoldLeft.Hold += h, 
       h => HoldLeft.Hold += h 
      ); 

     var rightHold = Observable.FromEvent<TCanvas.HoldHandler, GestureHoldEventArgs>(
       h => new TCanvas.HoldHandler(h), 
       h => HoldRight.Hold += h, 
       h => HoldRight.Hold += h 
      ); 

     var rightRelease = Observable.FromEvent<TCanvas.ReleaseHandler, EventArgs>(
       h => new TCanvas.ReleaseHandler(e => { }), 
       h => HoldRight.Release += h, 
       h => HoldRight.Release += h 
      ); 


     var leftRelease = Observable.FromEvent<TCanvas.ReleaseHandler, EventArgs>(
       h => new TCanvas.ReleaseHandler(e => { }), 
       h => HoldLeft.Release += h, 
       h => HoldLeft.Release += h 
      ); 

     leftHold.Subscribe(e => 
     { 
      _leftHeld = true; 
      DoCheck(); 
     }); 

     rightHold.Subscribe(e => 
      { 
       _rightHeld = true; 
       DoCheck(); 
      }); 

     rightRelease.Subscribe(e => 
     { 
      _rightHeld = false; 
      DoCheck(); 
     }); 


     leftRelease.Subscribe(e => 
     { 
      _leftHeld = false; 
      DoCheck(); 
     }); 

而且非常基本的DoCheck功能看起来是这样的....

private void DoCheck() 
    { 
     if (_rightHeld && _leftHeld) 
     { 
      MyTextBox.Text = (Convert.ToInt32(MyTextBox.Text) + 1).ToString() ; 
     } 
    } 

希望你能看到什么,我试图做的。每个画布都有一个保持和释放事件,所以当HoldLeft和HoldRight都被保持时,直到HoldRight或HoldLeft被释放。

任何帮助,将不胜感激。

回答

2

我相信我已经解决了我自己的问题。

而不是我为此付出的多个订阅。

 leftHold.Zip(rightHold, (a,b) => true) 
      .TakeUntil(leftRelease.Amb(rightRelease)) 
      .Subscribe(_ => TextOutput.Text = (Convert.ToInt32(TextOutput.Text) + 1).ToString()); 

它似乎做我想要的,但我打开进一步的建议/改进。

+0

这与我将要推荐的内容非常接近,非常简单而且很好。 – 2010-03-12 01:10:32

+1

这似乎并不像是正确的解决方案。 'Zip'将事件组合起来,因此需要在释放左边和右边之前再次拿起它们。如果我释放了权利,并再次举行这个可观察的将不会再次发射。我也会认为暂停事件只会触发一次,所以不应该有任何“TakeUntil”呼叫需要?你是怎么得到这个重新开始一对新的持有? – Enigmativity 2011-03-28 23:44:38

2

我遇到了这个答案,并认为它没有意义:

leftHold.Zip(rightHold, (a,b) => true) 
     .TakeUntil(leftRelease.Amb(rightRelease)) 
     .Subscribe(_ => TextOutput.Text = 
      (Convert.ToInt32(TextOutput.Text) + 1).ToString()); 
  • Zip对了事件,以便将 要求我释放左, 便又抱着他们。 如果我发布的权利,并再次举行它 这个可观察的将不会再发射 。
  • 我也会认为持有 的事件只会触发一次,所以有 应该不需要任何的 TakeUntil调用。
  • 另外我不明白这个答案会如何回复 refire - 它似乎只能得到一个 的值。

这里有一个选择:

var left = leftHold.Select(x => true).Merge(leftRelease.Select(x => false)); 
var right = rightHold.Select(x => true).Merge(rightRelease.Select(x => false)); 

var bothHold = 
    left.CombineLatest(right, (l, r) => l && r) 
     .Where(lr => lr == true) 
     .Select(lr => (Convert.ToInt32(MyTextBox.Text) + 1).ToString()); 

bothHold.Subscribe(t => MyTextBox.Text = t); 

我知道这个问题是一岁,但我很想知道如果我错过了一些东西,或者如果这个答案的作品。