4

I have a form that should capture KeyDown/KeyUp events.

This code fails with NRE, because it looks for KeyDown control on my current view:

this.BindCommand(ViewModel, vm => vm.KeyDown, "KeyDown");

What I've done is created wrapper class that has form as a property, so I can use this overload:

this.BindCommand(ViewModel, vm => vm.KeyDown, v => v.Form, "KeyDown");

While it works, it seems like a hack to me. Is there a proper way to bind to local events?

ionoy
  • 975
  • 6
  • 19

2 Answers2

7

That's the right way to do it if you're using BindCommand. If you want to get rid of the string and you're using ReactiveUI.Events, you could also do:

this.Form.Events().KeyDown
    .InvokeCommand(this, x => x.ViewModel.KeyDown);

As an aside, "KeyDown" isn't a very MVVM'y command. I'd write your key => command mappings at the View layer, like this (coding via TextArea, ignore syntax bugs):

this.Form.Events().KeyDown
    .Where(x => x.Key == Key.C && (x.Modifier & Modifier.Ctrl))
    .InvokeCommand(this, x => x.ViewModel.CopyText;
Ana Betts
  • 73,868
  • 16
  • 141
  • 209
  • 1. Can't I do this.Events()? – ionoy Mar 19 '14 at 08:11
  • 2. Is it possible to use Events() from WinForms? If not, then is it difficult to implement? – ionoy Mar 19 '14 at 08:12
  • You can, but you'll get a different object, no? Also Events doesn't exist for WinForms, you could probably build one if you rigged the RxUI source code to run through a different set of DLLs – Ana Betts Mar 19 '14 at 16:45
  • Seems like it would be easier for me to implement events-like extension methods myself inside my project. If I understand correctly, you are using some reflection based utility + ruby to generate Events assembly. You could also do this with Nemerle macros for much cleaner code. It would require Nemerle, though... – ionoy Mar 19 '14 at 18:49
  • Yeah, you could definitely do that too. Any IObservable will do – Ana Betts Mar 19 '14 at 18:54
2

I realize I'm really late to this particular party, but since I've been working on something similar, this is the approach I took, based on Paul's advice:

var keyDownSub= Observable.FromEventPattern<KeyEventHandler, KeyEventArgs>(
            ev => txtbxCommandLine.KeyDown += ev,
            ev => txtbxCommandLine.KeyDown -= ev
            ).Select(x => x.EventArgs)
            .Where(x => 
                x.KeyCode.ToString().ToUpper().Equals("RETURN") 
                && (_returnKeyPressed || x.Alt || x.Control))
            .InvokeCommand(_mainViewModel.ProcessCommandLine);

This seems to work perfectly fine in WinForms, if it is a bit more verbose than it would be in WPF.

Matt R.
  • 345
  • 1
  • 5
  • 15
  • 1
    Note you can use [reactiveui-events-winforms](https://www.nuget.org/packages/reactiveui-events-winforms/) to be non-verbose-like-wpf :) – Gluck Sep 24 '15 at 16:44