我正在使用observable来处理keydown事件。 我想发布一个observable,它总是设置关键,以处理消费者实际处理它的 iff 。 这可能吗?
以下是我现在处理密钥的示例:
KeyDown.Where(e => e.Key == Keys.W)
.Subscribe(e => { Console.WriteLine(e.Key); e.Handled = true; });
以下是我想要做的一个例子(如果之后自动设置处理属性,我也可以发布Keys而不是KeyDownEventArgs):
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();
});
此代码的问题在于,无论消费者是否实际处理了密钥,密钥都将始终设置为已处理。
有没有办法知道代码是否“已达到”订阅方法?
答案 0 :(得分:1)
您希望在KeyEventArgs
上超载订阅,以便在订阅后处理事件。听起来像是一个扩展名:
public static IDisposable SubscribeAndHandle(this IObservable<KeyEventArgs> input, Action<Keys> action)
{
return input.Subscribe(e => { action(e.KeyCode); e.Handled = true; });
}
然后,您只需使用SubscribeAndHandle
代替Subscribe
,只有在操作完成后才会将Handled
设置为true,并且操作可以使用Keys
而不是KeyEventArgs
{1}}:
var sub = KeyDown
.Where(e => e.KeyCode = Keys.W) // and so on
.SubscribeAndHandle(k => Console.WriteLine(k));
请注意,如果您不介意在执行操作之前将Do
设置为true,则可以在扩展方法中使用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));
}
答案 1 :(得分: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
扩展方法可让您“拦截”可观察内联的值。
如果有帮助,请告诉我。