La combinazione di più eventi in RX
-
19-09-2019 - |
Domanda
Ho 2 tocco abilitato su tela in un App Silverlight. Quello che devo fare è quando una persona tiene (presse e continua a premere) entrambe le tele, allo stesso tempo incrementare un valore sullo schermo una volta. Questo dovrebbe avvenire per ogni hold "doppio". Posso farlo bene usando gli eventi normali, ma provato a scrivere la stessa cosa usando RX e sto rimanere bloccati.
Al momento il mio codice è identico a quello approccio eventi separato (usando le variabili globali e metodo globale), ma penso che ci deve essere un modo migliore per comporre questo. Qualcuno può suggerire un approccio migliore?
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();
});
E la funzione molto di base DoCheck assomiglia a questo ....
private void DoCheck()
{
if (_rightHeld && _leftHeld)
{
MyTextBox.Text = (Convert.ToInt32(MyTextBox.Text) + 1).ToString() ;
}
}
Speriamo che si può vedere quello che sto cercando di fare. Ogni tela è un evento di attesa e di rilascio in modo che quando HoldLeft e HoldRight sono entrambi tenuti fare qualcosa fino a quando HoldRight o HoldLeft vengono viene rilasciato.
Qualsiasi aiuto sarebbe apprezzato.
Soluzione
Credo di aver risolto il mio problema.
Piuttosto che le molteplici sottoscrive sono andato per questo.
leftHold.Zip(rightHold, (a,b) => true)
.TakeUntil(leftRelease.Amb(rightRelease))
.Subscribe(_ => TextOutput.Text = (Convert.ToInt32(TextOutput.Text) + 1).ToString());
Sembra di fare quello che voglio, ma sono aperto ad ulteriori suggerimenti / miglioramenti.
Altri suggerimenti
Mi sono imbattuto in questa risposta e ho pensato che non aveva senso:
leftHold.Zip(rightHold, (a,b) => true)
.TakeUntil(leftRelease.Amb(rightRelease))
.Subscribe(_ => TextOutput.Text =
(Convert.ToInt32(TextOutput.Text) + 1).ToString());
- paia
Zip
gli eventi in modo sarebbe richiedono che ho comunicato a sinistra e destra prima di tenere di nuovo. Se ho rilasciato a destra e la tenne ancora una volta questo non sarebbe osservabile fuoco ancora una volta. - Ho anche potrebbe pensare che la stiva
eventi attiva una sola volta, quindi non c'è
non dovrebbe essere alcun bisogno di un
chiamata
TakeUntil
. - Anche io non vedo come questa risposta sarà refire - sembra avere una sola valore.
Ecco un'alternativa:
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);
So che questa domanda è un anno di età, ma mi piacerebbe sapere se ho perso qualcosa o se questa risposta funziona.