2016-03-31 40 views
0

Anahtarı "LeftShift + OemPlus" Anahtar "LeftShift + OemPlus" dan Tampon TextInput olaylar: .NET 4.6, C#, WPF, ReactiveExtension 2.2.5RX: Kullanılması

Benim Barkod-Scanner bir başlangıç ​​ve bitiş karakterini iletir (Code39, bu * karakterdir). PreviewKeyUp-Event'i kullanırken anahtar "LeftShift + OemPlus" dır. ReactiveExtensions kullanmaya çalışıyorum ama iki anahtarı nasıl alacağımı tam olarak bilmiyorum. Bu şimdiye kadar benim kodudur:

IObservable<EventPattern<KeyEventArgs>> keyDown = 
       Observable.FromEventPattern<KeyEventArgs>(this, "PreviewKeyDown"); 
IObservable<EventPattern<TextCompositionEventArgs>> textInput = 
       Observable.FromEventPattern<TextCompositionEventArgs>(this, "PreviewTextInput"); 
var textInputBuffer = textInput.Buffer(() => 
        keyDown.FirstOrDefaultAsync(t => t.EventArgs.Key == Key.OemPlus)); 

Şimdi "textInputBuffer" abone olabilir, ancak bu sadece yarım yapılır. Tamponun "SolShift" tuşu ile başlaması ve doğrudan "OemPlus" tuşunun basılmasından sonra başlamasını ve aynı tuş dizisi ile bitmesini istiyorum. Birisi hakkında bir fikrin var mı?

cevap

0

Bu sizi çalıştırıp çalıştırabilir.

var keyDown = Observable.FromEventPattern<KeyEventArgs>(this, "PreviewKeyDown"); 
var textInput = Observable.FromEventPattern<TextCompositionEventArgs>(this, "PreviewTextInput"); 

//Listen to pairs of events 
var boundaryEvent = keyDown.Buffer(2,1) 
    //Only yeild the pair of events if the pair is LeftShift and OemPlus 
    .Where(buffer => 
     buffer[0].EventArgs.Key == Key.LeftShift 
     && buffer[1].EventArgs.Key == Key.OemPlus); 


var query = from start in boundaryEvent 
      from text in textInput.Buffer(()=>boundaryEvent) 
      select text; 
//Or 
//var query = boundaryEvent.SelectMany(_=>textInput.Buffer(()=>boundaryEvent)); 

GÜNCELLEME İşte

bir kanıtlanabilir/tekrarlanabilir birim testidir güncelleştirilmiş örnektir. Umarım doğru

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reactive; 
using System.Reactive.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.Reactive.Testing; 
using NUnit.Framework; 

namespace StackOverflow.Q36340516_BufferedByBoundary 
{ 
    [TestFixture] 
    public class BufferByBoundary : ReactiveTest 
    { 
     [Test] 
     public void Should_yield_only_text_between_KeyPress_Boundary_events() 
     { 
      var scheduler = new TestScheduler(); 
      var observer = scheduler.CreateObserver<string>(); 
      //var keyDown = Observable.FromEventPattern<KeyEventArgs>(this, "PreviewKeyDown"); 
      //var boundaryEvent = keyDown.Buffer(2, 1) 
      // //Only yield the pair of events if the pair is LeftShift and OemPlus 
      // .Where(buffer => 
      //  buffer[0].EventArgs.Key == Key.LeftShift 
      //  && buffer[1].EventArgs.Key == Key.OemPlus) 
      // .Select(_=>Unit.Default); 
      var boundaryEvent = scheduler.CreateHotObservable(
       OnNext(0150, Unit.Default), //open 
       OnNext(0350, Unit.Default), //close 
       OnNext(0550, Unit.Default), //open 
       OnNext(0850, Unit.Default)); //close 

      //var textInput = Observable.FromEventPattern<TextCompositionEventArgs>(this, "PreviewTextInput") 
      //  .Select(evt=>evt.EventArgs.Text); 
      var textInput = scheduler.CreateHotObservable(
       OnNext(00100, "A"),  //before 1st open 
       OnNext(00200, "B"),  //buffer 1 
       OnNext(00300, "C"),  //buffer 1 
       OnNext(00400, "D"), 
       OnNext(00500, "E"), 
       OnNext(00600, "F"),  //buffer 2 
       OnNext(00700, "G"),  //buffer 2 
       OnNext(00800, "H")  //buffer 2 
       ); 

      var query = from start in boundaryEvent.Take(1) 
         from text in textInput.Buffer(() => boundaryEvent) 
         select string.Join(string.Empty, text); 

      query.Take(1).Repeat().Subscribe(observer); 

      scheduler.Start(); 

      CollectionAssert.AreEqual(new[] 
      { 
       OnNext(350, "BC"), 
       OnNext(850, "FGH"), 
      }, 
      observer.Messages); 
     } 
    } 
} 
+0

içinde 1 atlamak almak için gerekli mods görebilirsiniz 'keyDown.Buffer' textInput.Buffer'' kapanış seçici için accout etmektir? – supertopi

+0

Hayır, 'Arabellek (2,1)', aynı diziden çakışan çiftleri almak için kullanılan bir kalıptır. Bunu yapmanın diğer yolları Publish(). RefCount() sonra 'shared.Zip (shared.Skip (1), (a, b) => Tuple.Create)' ya da 'Scan' kullanmak ancak Buffer (2, 1) '' etrafında çok az çözülüyor. –

+0

Eh, bu çok yakın, ama ... İlk kez girdiğimde "* aaa *" "aaa" gibi bir şey elde ediyorum. Bundan sonra "*" giriyorum ve "**" yi alıyorum, sonra "bbb *" yazıp "* bbb * bbb * bbb", sonra beş kez "* ccc", yedi kez "* ddd" yazdım. . Aradaki arabelleği temizlemenin bir yolu olmalı. – okieh