Keyboard Input Return Key - c#

I am programming a calculator in C#, and I am trying to add keyboard input to it. The problem is if I click a button on the GUI then the Enter/Return key gets focused on that. When the return key is pressed it then clicks that key again, instead of being handled by my KeyDown event handler. How can I fix this?
private void Window_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.NumPad1:
case Key.D1:
addInput('1');
break;
case Key.Return:
MessageBox.Show("Enter!");
break;
}
}

You need to handle PreviewKeyDown event of your form. Then check if you want to handle the event, and if you do, set Handled property of the event to true after you do.
That would probably look something like this:
public MainWindow()
{
InitializeComponent();
PreviewKeyDown += new KeyEventHandler(MainWindow_PreviewKeyDown);
}
void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
Log("Intercepted space in preview");
e.Handled = true;
}
}
Why do you need to set Handled to true? Events in WPF are triggered on several UI elements, in manner which depends on it's "routing strategy". When your event handler sets Handled to true, visibility of that event will be limited to other UI elements. Shortly, it won't be triggered in other UI elements. To learn more about details of solution above, read rest of the answer below.
There are some things that you need to understand if you want to properly use events in WPF. Events are attached to UI elements (text boxes, buttons, etc), and event handlers can be connected to those UI elements. Also, UI elements are organized in a tree structure. Each element has it's parent element, up to root UI element. As already mentioned, events are triggered on multiple elements depending on their "routing strategy". Multiple elements here means element at which an event is targeted and it's parents, up until root element. Event routing strategy can be following:
Bubbling: Event is first fired for event target element. Then, it is fired for it's parent, then parent of it's parent, and so on up until root element (often this is Window)
Tunneling: Event is first fired for root UI element, and then down UI elements tree, along the route to target element.
Direct: Event is only fired for target element.
How is this related to Handled property? When event is using bubbling or tunneling routing strategy, Handled property is used to stop propagation of event down or up UI elements tree.
Now, why didn't KeyDown event stop propagating when you marked it as Handled? Because KeyDown event uses bubbling strategy. This means that a text box would already handle KeyDown event, before it get's to Window handler where you set Handled to true.
For that reason you should use PreviewKeyDown which uses tunneling strategy. Your window handler checks the event, marks it as Handled if needed. If it's marked as Handled it will not be triggered down UI tree to event target.
You can view this as a convention in .NET framework. PreviewX are events which use tunneling strategy, and are counterpart of X events which use bubbling strategy.
To learn more about Routed Events visit this MSDN page. You'll find MSDN is a good source of information about WPF.

Try this:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.NumPad1:
case Key.D1:
addInput('1');
MyTextBox.Focus(); // <-- NEW LINE OF CODE
break;
case Key.Return:
MessageBox.Show("Enter!");
MyTextBox.Focus(); // <-- NEW LINE OF CODE
break;
}
}

set Focusable to false:
<Button Focusable="False" Click="Button_Click" />

Related

Window.Current.CoreWindow KeyDown Event won't fire for "Tab" key Pressed in c#?

what I have Tried is ?
Window.Current.CoreWindow.KeyDown += keydown;
private void keydown(CoreWindow sender, KeyEventArgs args)
{
//Printing entered key
}
I'm developing UWP application.In my app Window.Current.CoreWindow
keydown event fired for all the keys in keyboard except "Tab" key.
I don't know why the event don't fire for that specific key?I want to do some actions while "Tab" key is pressed. Anyone know, how to fire the event when "Tab" key is pressed ?
By testing, sometimes pressing Tab key will not trigger CoreWindow.KeyDown event handler when there are some controls such as Button can get focus in a page. You could try to add a UIElement.KeyDown event or a UIElement.PreviewKeyDown event to a page(such as MainPage) in xaml file.
Update:
When you use CoreWindow.KeyDown event and there are controls which could get focus in your page, pressing Tab key will let the focus step into a tab sequence instead of triggering the CoreWindow.KeyDown event. The CoreWindow.KeyDown event could be triggered when Tab key is pressed and the focus locates at the last control which could get focus.
If you want CoreWindow.KeyDown event to be triggered when Tab key is pressed, you could set TabNavigation as Once in your page. If you want save the Tab key’s feature that stepping into tab sequence, we still suggest you use UIElement.KeyDown event or UIElement.PreviewKeyDown event.
For example:
Window.Current.Content.KeyDown += Content_KeyDown;
Update:
Window.Current.Content.KeyDown event is a routed event. About routed event, you could refer to the document. A routed event is an event that is potentially passed on (routed) from a child object to each of its successive parent objects in an object tree.
In your scenario, you could monitor the value of e.OriginalSource and you could view that when you step into the last control which could get focus by pressing Tab key the KeyDown event will be triggered twice. In the second trigger, the value of e.OriginalSource could be Windows.UI.Xaml.Controls.Frame( may be different, subject to your observation in the second trigger). That’s because the routed KeyDown event need to bubble to its parent object at this time. You could add some code to identify the second trigger.
For example:
private void Content_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalSource.ToString()!= "Windows.UI.Xaml.Controls.Frame")
{
//Just be fired once here
}
}
Note, you could try to use code e.Handled = true; to stop the routed behavior referring to here. And, if you use Page.KeyDown event, there is no situation that KeyDown event be triggered twice.

Raise Event on When a different event raised - C#

I have made my own Button User control in a WPF application.
In this, I'm trying to raise a event attached with multiple event handlers on another event.
I have multiple event handlers attached with "MouseUp" Event for View and business logic (MVVM). I just want to fire all the handlers attached with "MouseUp" event On "KeyUp" with "Enter" and "SpaceBar"
Here is the sample code which I used to raise "MouseUp" event on "KeyUp" if the key is enter or space
void Button_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space || e.Key == Key.Enter)
{
RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{
RoutedEvent = Mouse.MouseUpEvent,
Source = this,
});
}
}
Not sure. I may be wrong. But it worked for me. However, not in all case.
In some of the cases, the event not raising as expected.
In my further investigation, Im seeing the key up event get triggered. But the none of the event handlers in "MouseUp" event raised in some objects.
Is there any elegant way to achieve my need.
This breaks the expected pattern for anyone reading the code - why would the mouseup event need to be fired when the key is released? If it's just to avoid code duplication, you should have a separate method which both the mouseup and the keyup call.
As per the comments, if you have multiple event handlers attached, you will need to attach all of them to both events. Alternatively, you could create a meta-event-handler that calls all the others as methods, then just attach that one to each event.
Just create function and work with events separately, adding reference to this function as events handler.

Can anyone raise any RoutedEvent in WPF?

In C# events were always very protected: Only the owner of the event could trigger them. However, this seems to be completely different in WPF - Anyone can throw any event at any time. To test that, I've written the code in the bottom.
When I used RaiseEvent to raise Button.Click, the event above caught it. Is that the planned behavior of WPF events? Just letting anyone throw any events they wish? Also, if so, then what is the meaning of the OwnerType when you register the event? I thought it is some kind of protection, yet if it is, it is a poor one since anyone can access the public event and use AddOwner function to add more owners.
Thanks!
XAML
<StackPanel Button.Click="ButtonBase_OnClick">
<Button Name="RealButton">Real button</Button>
<WpfWindow:VitalyControl MouseDown="UIElement_OnMouseDown">
I am almost a button
</WpfWindow:VitalyControl>
</StackPanel>
Code behind
The custom control:
class VitalyControl : Label
{
public VitalyControl()
{
this.MouseDown += new MouseButtonEventHandler(VitalyControl_MouseDown);
}
void VitalyControl_MouseDown(object sender, MouseButtonEventArgs e)
{
RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
}
}
And the handler:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button was pressed");
}
This is by design, and is actually one of the reasons for RoutedEvents. They are called routed events because they are routed across the element tree. The behavior you are experiencing is called 'singular handler attachment point' on msdn. You specify that StackPanel should listen to all Button.Click events.
In your custom control, you raise a button click event. This 'bubbles' up to the stackpanel, which handles it.
UPDATE:
For this routing to work, I assume every UIElement needs to be able to raise any routed event. Routed Events are only used by UI elements, and are an answer to complexities with WinForms implementations. They aren't a replacement for CLR events.
The owner type is used internally when resolving an event by name.

Overriding keypress

I know this may be an easy answer to some of you but i dont know how to properly do this. Ive created a text editor, that also has a docking window that will display functions. I have it set up in the menu that F8 is the shortcut key for showing the function window. I would also like to catch the F8 keypress event to parse the current data for the functions in the program but I cant get this to happen..
Capture your Text Editors KeyPressed Event and check the KeyEventArgs that are coming in, then mark the not handled as false which will cause the event to be passed up to the parent control:
Example
KeyPressed(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F8) DoSomething();
e.Handled = false;
}
In response to the comment that you added to your question. You may need to set the controls KeyPreview to True. I think that KeyPreview may be available at only the form level, but I'm not sure.
Set up an event handler for the OnKeyPress (or OnKeyDown or OnKeyUp) event, and check which key was pressed (it will be in the event arguments). Then, you can do whatever you want.
I don't think the tagged answer is correct. The KeyPress event handler won't handle the Function keys; you need to use KeyUp event handler or ProcessDialogKey method.
I'm not sure to understand everything, but can't you use the KeyPress Event available in any Control ?

Winform keyboard management

I would like to control the focus of my winform application. It is made of a custom listbox and several other component.
I want all the keyboard event be managed by my window handlers in order to avoid specific control key handling (for example when I press a character and the list box is focused, the item starting with the correspondant letter is selected which is not a correct behaviour for my application).
How can I achieve this?
Make sure your form's KeyPreview property is set to true. Then this code should work for canceling your key events to the listbox...
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (this.ActiveControl == listBox1)
e.Handled = true;
}
The KeyPress event may not work for all your scenarios. In that case, I would try out the KeyDown event.

Categories