简体   繁体   中英

How to create a KeyEventArgs object in WPF ( related to a SO answer )

I've found this answer which look like what I need:

How can I programmatically generate keypress events in C#?

Except for the fact I can't create an instance of KeyEventArgs ( I don't know how )

The code in question is:

 var key = Key.Insert;                    // Key to send
  var target = Keyboard.FocusedElement;    // Target element
  var routedEvent = Keyboard.KeyDownEvent; // Event to send

  target.RaiseEvent(
    new KeyEventArgs(
      Keyboard.PrimaryDevice,
      PresentationSource.FromVisual(target), //<--- HERE, I can't
      0,
      key)
    { RoutedEvent=routedEvent }
  );

The compiler says:

The best overloaded method match for
'System.Windows.PresentationSource.FromDependencyObject(System.Windows.DependencyObject)'
 has some invalid arguments

The ide says:

Argument type IInputElement is not assignable to parameter type DependencyObject

And across StackOverflow I've found several answers directing to that answer but none of them address how to create the instance in first place.

How can I do that?

phewwww

I've found it: Keyboard.PrimaryDevice.ActiveSource has to be used

InputManager.Current.ProcessInput(
    new KeyEventArgs(Keyboard.PrimaryDevice,
        Keyboard.PrimaryDevice.ActiveSource,
        0, Key.Tab)
    {
       RoutedEvent = Keyboard.KeyDownEvent
    }
);

Similar to Bill Tarbell's answer, you can also create a dummy System.Windows.Interop.HwndSource , like so:

var kea = new KeyEventArgs(
    Keyboard.PrimaryDevice, 
    new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero), // dummy source
    0, 
    key);

If anyone is trying to create the KeyEventArgs for use in a unit test you'll find that Keyboard.PrimaryDevice.ActiveSource is null.. and throws an exception when you try to use it.

Mocking a PresentationSource is a workable solution (requires sta):

[Test]
[RequiresSTA]
public void test_something()
{
  new KeyEventArgs(
    Keyboard.PrimaryDevice,
    new Mock<PresentationSource>().Object,
    0,
    Key.Back);
}

To unit test a viewmodel I had to use a combination of OscarRyz and Elijah W. Gagne answer to make this work.

    [TestMethod]
    public void method_event_expected()
    {
        this.objectUnderTest.TestMethod(
            new KeyEventArgs(Keyboard.PrimaryDevice, new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero), 0, Key.Oem3)
            {
                RoutedEvent = Keyboard.KeyDownEvent
            });

        Assert.IsTrue(...)
    }

Keyboard.PrimaryDevice.ActiveSource was null so I had to fake it with a dummy window and then I also needed the RoutedEvent to be assigned.

var kea = new KeyEventArgs(
    Keyboard.PrimaryDevice,
    new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero),
    0,
    Key.Enter)
    {
        RoutedEvent = UIElement.KeyUpEvent
    };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM