0

キーダウンイベントを処理するためにオブザーバブルを使用しています。オブザーバブルを公開したいと思います。これにより、消費者が実際に処理した場合に処理されるキーが常に設定されます。これは可能ですか?

これが、現在処理されるキーを設定する方法の例です。

KeyDown.Where(e => e.Key == Keys.W)
.Subscribe(e => { Console.WriteLine(e.Key); e.Handled = true; });

これが私がそれをどのようにしたいかの例です(処理されたプロパティが後で自動的に設定された場合、KeyDownEventArgsの代わりにKeysを公開することもできます):

HandledKeyDown.Where(k => k == Keys.W).Subscribe(k => Console.WriteLine(k));

これが私が試したことです:

HandledKeyDown = Observable.Create<Key>(observer => {
    var keys = KeyDown.Subscribe(e => { e.Handled = true; observer.OnNext(e.Key); });
    return () => keys.Dispose();
});

このコードの問題は、コンシューマーが実際にキーを処理したかどうかに関係なく、キーが常に処理済みとして設定されることです。

コードがサブスクライブメソッドに「到達」したかどうかを知る方法はありますか?

4

2 に答える 2

1

必要なのは、サブスクリプションをオーバーロードしKeyEventArgsて、サブスクリプション後に処理されるイベントを作成することです。拡張機能のように聞こえます:

public static IDisposable SubscribeAndHandle(this IObservable<KeyEventArgs> input, Action<Keys> action)
{
    return input.Subscribe(e => { action(e.KeyCode); e.Handled = true; });
}

次に、SubscribeAndHandleの代わりにを使用します。これは、アクションが実行された後にのみtrueSubscribeに設定され、アクションは使用できません:HandledKeysKeyEventArgs

var sub = KeyDown
          .Where(e => e.KeyCode = Keys.W) // and so on
          .SubscribeAndHandle(k => Console.WriteLine(k));

アクションが実行される前にtrueに設定されてDoいてもかまわない場合は、代わりにextensionメソッドを使用できることに注意してください。Handledこれは、副作用を実行するためのよりクリーンな方法です。

public static IDisposable SubscribeAndHandle(this IObservable<KeyEventArgs> input, Action<Keys> action)
{
    return input.Do(e => e.Handled = true)
                .Select(e => e.KeyCode)
                .Subscribe(e => action(e));
}

@Enigmativityからの有益なコメントはHandled、サブスクリプション内からがtrueに設定されているかどうかを判断したい場合があることを示唆しています。これは非常に簡単です。拡張メソッドを変更して、 :Func<Keys,bool>ではなく受け入れるようにします。Action<Keys>

public static IDisposable SubscribeAndHandle(this IObservable<KeyEventArgs> input, Func<Keys,bool> action)
{
    return input.Subscribe(e => e.Handled = action(e.KeyCode));
}
于 2012-05-07T04:43:31.970 に答える
0

私はこのようなことをすることを検討します:

var HandledKeyDown =
    KeyDown
        .Do(e => { /* Handling Code Here */ })
        .Where(e => e.Handled)
        .Where(e => e.Key == Keys.W)
        .Select(e => e.Key)
        .Subscribe(k => Console.WriteLine(k));

拡張メソッドを使用するDoと、監視可能なインラインの値を「インターセプト」できます。

これが役立つかどうか教えてください。

于 2012-05-07T00:17:50.627 に答える