uwp page not firing keydown event at all - c#

in my uwp app I just added a new page and navigated to it, and I have nothing on that page just the default grid. but I am trying to recieve keydown events which is not firing up by any key at all. I have also put keydown to the grid on xaml and to the page in code behind, but it is still not firing up I have assured that with break points.
xaml
<Grid KeyDown="VideoPageKeyDown">
</Grid>
code behind
public sealed partial class VideoPlay : Page
{
public VideoPlay()
{
this.InitializeComponent();
KeyDown += VideoPageKeyDown;
}
private void VideoPageKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.GamepadDPadDown
|| e.Key == VirtualKey.GamepadLeftThumbstickDown)
{
//VideoMenuGrid.Visibility = Visibility.Visible;
//await VideoMenuGrid.Offset(200f, 0f, 1000, 0).StartAsync();
}
else if (e.Key == VirtualKey.GamepadDPadUp
|| e.Key == VirtualKey.GamepadLeftThumbstickUp)
{
//await VideoMenuGrid.Offset(0f, 0f, 1000, 0).StartAsync();
//VideoMenuGrid.Visibility = Visibility.Collapsed;
}
}
}

Controls like the grid that do not get focus will not receive the event directly. If there is another control on top of it might pass the event to the grid because it is an routed event. Thy using the coreWindow keyDown event instead.
public sealed partial class VideoPlay : Page
{
public VideoPlay()
{
this.InitializeComponent();
//Add this line
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs e)
{
//todo
}
}

Related

Do not trigger click on focused element when hitting ctrl+space

In my WPF application a "global" search box appears when hitting Ctrl+Space. It behaves like Spotlight in Mac OS when hitting Command+Space.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public static RoutedCommand OpenSpotlight { get; set; } = new RoutedCommand();
public MainWindow()
{
OpenSpotlight.InputGestures.Add(new KeyGesture(Key.Space, ModifierKeys.Control));
}
private void OpenSpotlight_Execute(object sender, ExecutedRoutedEventArgs e)
{
// Code which opens the search box ...
}
}
MainWindow.xaml
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.OpenSpotlight}" Executed="OpenSpotlight_Execute"/>
</Window.CommandBindings>
Works fine, except one problem: when any button is focused, hitting Ctrl+Space triggers the button to be clicked because Space key is being hit.
Is there any way to omit this behaviour? I think of changing/removing the focus globally when Ctrl key is hit but don't know how this can be implemented ...
Instead of using a RoutedCommand and a CommandBinding, you could just handle the PreviewKeyDown event:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PreviewKeyDown += OnPreviewKeyDown;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space
&& (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
e.Handled = true;
// Code which opens the search box ...
}
}
}
This solution doesn't require you to add anything to the XAML markup.
I haven't tried this, but seems quite logical to me.
You can handle the KeyDown and/or PreviewKeyDown event of a button and skip the Space press. Something like this could work :
private void GlobalButton_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
Wondering how you'ld do this for all the buttons? Here's a function to find a control of a given type:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T :
DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Simply loop through the buttons on window_load or similar events:
foreach (Button btn in FindVisualChildren<Button>(this))
{
btn.KeyDown += GlobalButton_PreviewKeyDown;
btn.PreviewKeyDown += GlobalButton_PreviewKeyDown;
}
Hopefully this helps.

Handling some keys while textbox is focused

So, apparently I had some problem when handling keys such as F10 or F11.
I want to move the focus from current textbox into another textbox, but not in one particular textbox. So, I wrote some code to handle key:
private void checkKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
buyerName.Focus();
}
else if (e.KeyCode == Keys.F11)
{
discount.Focus();
}
}
But, if I put this into individual textbox, which kinda hassle to me. Is there any method to listen key whether in global userControl or textbox?
Edit : here's my structure that I want to ask :
Form-
|-User Control
|-TextBox
Edit 2 : here's some image might help img
To use a global keyboard listener in Winforms, you just need to add a handler to KeyUp action for the main form itself:
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true; //To use F10, you need to set the handled state to true
} else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
}
}
Then make sure that the KeyPreview property on the main form is set to True.
The issue with the application freezing when pressing F10 is because it is waiting for another consecutive action. To bypass this simply set the Handled property on the keyevent to TRUE. This releases the unresolved event.
This is my entire form class, refactored to use a helper method as you are refering to. This works fine. But you have to make sure that the KeyPreview property on your form is True, unless your keypresses will not be matched to your event handlers.
namespace KeyTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
CheckKeys(e);
}
private void CheckKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true;
}
else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
e.Handled = true;
}
}
}
}
Now in your comment you are mentioning a UserControl, if you want that, then you need to create an instance method on your UserControl class, and pass the event to that from your global keyboard event handler on your main form.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public void HandleKeys(KeyEventArgs e)
{
if (e.KeyCode == Keys.F10)
{
textBox1.Focus();
e.Handled = true;
}
else if (e.KeyCode == Keys.F11)
{
textBox2.Focus();
e.Handled = true;
}
}
}
Then on your main form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
CheckKeys(e);
}
private void CheckKeys(KeyEventArgs e)
{
uc1.HandleKeys(e); //Instance method on your user control.
}
}
This then works as intended.
As pointed out in one of the comments, a better way would be to override the ProcessCmdKey method on the Form base class. This would be done like so:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
userControl11.HandleKeys(keyData); // method on the userControl to handle the key code.
base.ProcessCmdKey(ref msg, keyData);
return true;
}
}
The handler on the UserControl stays more or less the same:
public void HandleKeys(Keys keys)
{
if (keys == Keys.F10)
{
nameTB.Focus();
} else if (keys == Keys.F11)
{
emailTB.Focus();
}
}
Whether this is a more correct way of doing it, I am unsure of. They certainly both accomplish the same result. The documentation shows the first method in for handling keyboard events at the form level here:
How to handle keyboard input
But states here that the ProcessCmdKey method is to provide additional handling of shortcuts and MDI accellerators.
ProcessCmdKey
I will leave that up to you to decide what is the best for your scenario. But keep it in to show how you would use it should you choose to.
You can hook up to the KeyUp event of your form.
That way, any key pressed while your form is focused will be send to you (if the control didn't handle the key).
Thanks to #Espen and #reza-aghaei for handling keys into main form. Unfortunately, I still didn't managed find a way to focus to designated textbox inside a UserControl. However, I make some dirty method which kinda crappy and un-efficient by searching child control from it's parent
//MainForm.cs
if(yourUserControl.Name)//Do some check for targeted userControl, if null can cause NullReferenceException
{
if (e.KeyCode == Keys.F10)
{
this.Controls.Find("textboxName", true).First().Focus();
e.Handled = true;
}
}

How to use the back function in UWP apps to change visibility of a grid?

I would like to use the back function in the UWP in the App.xaml.cs file to change the visibility property of a grid (grid1) on the MainPage.xaml file.
//Go Back
public void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
if(MainPage.MyGlobals.pageLocation == 0)
{
//Do Nothing
}
else if(MainPage.MyGlobals.pageLocation == 1)
{
MainPage.grid1.Visibility = Visibility.Collapsed;
MainPage.MyGlobals.pageLocation = 0;
}
}
I know it's not typical practice to change xaml elements' properties from a different page, but I would really like to change how the back feature works in this app. I believe I have to make the grid pubic, but even when I (thought I) found a way to do that I still couldn't change the properties of the grid with the way I have it written in my code.
As you've mentioned, changing XAML elements' properties from a different page is not a good practice. We can just use SystemNavigationManager.BackRequested event in MainPage like following to change the visibility of a grid.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested += Page_BackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested -= Page_BackRequested;
}
private void Page_BackRequested(object sender, BackRequestedEventArgs e)
{
if (MyGrid.Visibility == Visibility.Visible)
{
MyGrid.Visibility = Visibility.Collapsed;
e.Handled = true;
}
else
{
if (this.Frame.CanGoBack)
{
this.Frame.GoBack();
e.Handled = true;
}
}
}
And if you want to take advantage of the back function in App.xaml.cs and use a different function in MainPage, you can add a event in App that wraps SystemNavigationManager.BackRequested to allow other pages to override the default behavior by subscribing to this event like following:
public event EventHandler<BackRequestedEventArgs> BackRequested;
private void App_BackRequested(object sender, BackRequestedEventArgs e)
{
BackRequested?.Invoke(sender, e);
Frame rootFrame = Window.Current.Content as Frame;
if (!e.Handled && rootFrame != null && rootFrame.CanGoBack)
{
rootFrame.GoBack();
e.Handled = true;
}
}
Then in MainPage, subscribe and unsubscribe this event like:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
(Application.Current as App).BackRequested += Page_BackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
(Application.Current as App).BackRequested -= Page_BackRequested;
}
It doesn't work because you're trying to access the Grid as if it was a static property of the MainPage. You need a reference to the MainPage instance to manipulate the Grid, but all in all it is a really bad practice. You should have a look at the UWP/WP 8.1 navigation events.

c# pass keydown from form to usercontrol

I have a calculator usercontrol, the usercontrol is added to a panel in my form:
On my main Form I have:
private void frmPOS_KeyDown(object sender, KeyEventArgs e)
{
// here I want to pass the keydown captured to my calculator
// usercontrol so the KeyDown event is fired in my usercontrol
}
In my Calculator.cs I have:
private void Calculator_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.NumPad0:
// one
lblResult.Text = "0";
break;
case Keys.NumPad1:
// one
lblResult.Text = "1";
break;
case Keys.NumPad2:
// two
lblResult.Text = "2";
break;
// .. etc
case Keys.Add:
// Plus
break;
default:
// Avoid setting e.Handled to
return;
}
e.Handled = true;
}
Any clue?
One way I have done this is by creating an event on the user control and raise it when the actual event happens. So, in the user control I would do something like...
public partial class Calculator : UserControl
{
//create an event
public event EventHandler<KeyPressEventArgs> OnKeyPressed;
public Calculator()
{
InitializeComponent();
}
private void Calculator_KeyPress(object sender, KeyPressEventArgs e)
{
//raise the event when the key press happens and someone is listening
if (OnKeyPressed != null)
{
OnKeyPressed(sender, e);
}
}
}
and then on the Main form you would subscribe to the event and handle it..
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//subscribe to the event we create on the user control
calculator1.OnKeyPressed += new EventHandler<KeyPressEventArgs>(MyKeyPressHandlerInMainForm);
}
private void MyKeyPressHandlerInMainForm(object sender, KeyPressEventArgs e)
{
//Handle the event. Here you would write your logic.
//Since you have keypressEventArgs coming in as a parameter you would be able to
//do determine what key was pressed and all that.
}
}
enter code here
You can move your switch block to a new public method in the control, eg.:
public void HandleKeyEvent(KeyEventArgs e) { ... }
This method can be invoked from your form (and your existing control event handler if you need to keep it).
As a side note, if you set the form's KeyPreview-property to true you won't get problems with a focused control incorrectly getting the event. See MSDN for more information about this property.

How to get Usercontrol object 'X' from X's Button(i.e. Button inside the X) onclick event

Hello guys i am working on a Windows Form application in .Net C#.
Now i have a User control with a button inside it.
however i had to write the on-click handler in the main form rather than inside the user-control itself.
Now i want to know if there is anyway i can get the User-control object in the Button's on-click Handler. Since i had to make use of them few more times in the same form. I want to know which User-control's Button was click.
User Control
Button
Thank You :)
Here's an example of the UserControl raising a Custom Event that passes out the source UserControl that the Button was clicked on:
SomeUserControl:
public partial class SomeUserControl : UserControl
{
public event ButtonPressedDelegate ButtonPressed;
public delegate void ButtonPressedDelegate(SomeUserControl sender);
public SomeUserControl()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (ButtonPressed != null)
{
ButtonPressed(this); // pass the UserControl out as the parameter
}
}
}
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
someUserControl1.ButtonPressed += new SomeUserControl.ButtonPressedDelegate(SomeUserControl_ButtonPressed);
someUserControl2.ButtonPressed += new SomeUserControl.ButtonPressedDelegate(SomeUserControl_ButtonPressed);
someUserControl3.ButtonPressed += new SomeUserControl.ButtonPressedDelegate(SomeUserControl_ButtonPressed);
}
void SomeUserControl_ButtonPressed(SomeUserControl sender)
{
// do something with "sender":
sender.BackColor = Color.Red;
}
}
You can use event:
public delegate void ButtonClicked();
public ButtonClicked OnButtonClicked;
You can then subscribe the event anywhere, for instance, in your MainForm, you have a user control called demo;
demo.OnButtonClicked +=()
{
// put your actions here.
}
Just walk the .Parent() chain until you find a Control that is the same Type as your UserControl. In the example below, the UserControl is of Type SomeUserControl:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
someUserControl1.button1.Click += new EventHandler(button1_Click);
someUserControl2.button1.Click += new EventHandler(button1_Click);
someUserControl3.button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
Control uc = btn.Parent;
while (uc != null && !(uc is SomeUserControl))
{
uc = uc.Parent;
}
uc.BackColor = Color.Red;
MessageBox.Show(uc.Name);
}
}

Categories

Resources