2010-03-11 79 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); 

我知道這個問題是一歲,但我很想知道如果我錯過了一些東西,或者如果這個答案的作品。