I have a few controls in a Form, so I read and create a Event in the form that allows me to press ENTER to change the focus to another control. Here's the code:
private void frSeleccionEL_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
Control nextControl = this.GetNextControl(ActiveControl, !e.Shift);
if (nextControl != null)
{
e.Handled = true;
if (!(nextControl is Label))
{
nextControl.Focus();
}
else //the next control is currently a label
{
nextControl = this.GetNextControl(ActiveControl, true);
while (nextControl != null)
{
nextControl.Focus();
if (!(nextControl is Label))
{
break;
}
nextControl = this.GetNextControl(ActiveControl, true);
}
}
}
}
}
In the textbox where it's not working, I have code for only numbers. Here's the code:
private void txtLocal_KeyPress(object sender, KeyPressEventArgs e)
{
//Para obligar a que sólo se introduzcan números
if (Char.IsDigit(e.KeyChar))
{
e.Handled = false;
}
else
{
if (Char.IsControl(e.KeyChar)) //permitir teclas de control como retroceso
{
e.Handled = false;
}
else
{
//el resto de teclas pulsadas se desactivan
e.Handled = true;
}
}
}
My problem is when I press ENTER in this control nothing happens, like ENTER was never pressed, because the event keypress for this control doesn't fire.
I deleted the control and remade it and the problem remains.
I don't know what is wrong.
Your first code is too long and we don't need it. If you want to turn Enter keypress into a Tab switch, using SelectNextControl method of your form. I can see your txtLocal_KeyPress does nothing with switching tab, so how you knew what happened or not. e.Handled only helps suppress the key press event or not. I guess your TextBox has Multiline = true; and you want to suppress the Enter keypress, instead switch to the next control, otherwise you don't have to suppress the Enter keypress in TextBox with Multiline=false. This short code will help you:
private void txtLocal_KeyPress(object sender, KeyPressEventArgs e){
if(e.KeyChar == 13)//Enter{
e.Handled = true;
SelectNextControl(txtLocal, true, true, true, true);
}
}
That's all to solve your problem.
I'm not sure if you know how to register a KeyPress event handler with your TextBox.KeyPress event, so I add this here to help you in that case:
txtLocal.KeyPress += txtLocal_KeyPress;
Try this:
private void txtLocal_KeyPress(object sender, KeyPressEventArgs e)
{
//Para obligar a que sólo se introduzcan números
if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar) )
{
e.Handled = true;
}
}
please use this code on form key down this will give you better performance
private void frSeleccionEL_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
ProcessTabKey(true);
}
}
please make sure you have set tab index on all of your control.
and then unchanged your text changed event code. it will be better if you use a custom text box instead of writing this code on all of your form.
Try this ......
private void txtLocal_KeyPress(object sender, KeyPressEventArgs e)
{
//Para obligar a que sólo se introduzcan números
if (Char.IsDigit(e.KeyChar) || asc(e.KeyChar)==13)
{
e.Handled = false;
}
else
{
if (Char.IsControl(e.KeyChar)) //permitir teclas de control como retroceso
{
e.Handled = false;
}
else
{
//el resto de teclas pulsadas se desactivan
e.Handled = true;
}
}
}
If you want to commit your changes with the enter key, assuming you want to update your data bindings, but stay in the control you can use the following code
private void TextBox_KeyPress(object sender, EventArgs e)
{
if(e.KeyCode == (char)Keys.Enter)
{
TextBox.DataBindings[0].WriteValue();
dataBindingSource.ResetCurrentItem();
TextBox.Select(TextBox.Text.Length, 0);
e.Handled = true;
}
}
The important part there is WriteValue() which commits the changes before the databind event fires. If you want other controls to update on your form after committing the changes, the ResetCurrentItem() will do this. Also, this code just commits the first binding value, but if you have multiple bindings you can step through them with a foreach loop and WriteValue() all of them or whatever. The TextBox.Select() line just keeps your cursor where you left it after pressing enter.
Related
I am trying to warn the user when they select and delete text in a wpf textbox.
I am able to trap the delete event using the previewkeydown event, but its is canceling out the delete event. Even when you press ok in the code below - deletion does not happen. I am missing something ...
private void TextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Delete)
{
var textbox = (TextBox)sender;
if (textbox.SelectionLength > 1)
{
var result = MessageBox.Show("Delete selected?", "MyApp", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.Cancel)
{
e.Handled = true;
}
}
}
}
This does not seem to be the proper usage of the PreviewKeyDown event handler. That handler seems to be meant to redirect non-standard input key events to do custom behavior. The delete key is not considered non-standard/special.
You've got the right idea with your current code otherwise, but now you just need to actually delete the text in the textbox.
private void TextBox_KeyDownHandler(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Keys.Delete:
if (sender is TextBox tb)
{
if(tb.SelectionLength > 1 && MessageBox.Show("Delete?", "MyApp", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
tb.SelectedText = "";
}
}
e.Handled = true;
break;
}
}
Lastly, make sure you're actually subscribing your handlers
public MainWindow()
{
InitializeComponent();
MyTextBox.KeyDown += new KeyEventHandler(TextBox_KeyDownHandler);
}
I'm working on a text editing UwP Desktop application that needs to add a line when the user presses ENTER, and perform another procedure when the user presses CTRL + ENTER. The problem is to delete the new line that is also created in the second case. How to prevent this from happening?
KeyEventHandler keyeventHandler = new KeyEventHandler(rtbText_KeyDown);
rtbText.AddHandler(TextBox.KeyDownEvent, keyeventHandler, true);
private static bool IsCtrlKeyPressed()
{
var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
}
private void rtbText_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (IsCtrlKeyPressed())
{
switch (e.Key)
{
case VirtualKey.Enter:
NviNew_Tapped(nviNew, null);
e.Handled = true;
break;
}
}
}
You can use PreviewKeyDown Event as keydown event will not fire for system handled keys
private void TextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down)&& e.Key == Windows.System.VirtualKey.Enter)
{
e.Handled = false;
}
}
As #Vignesh said, you can use PreviewKeyDown Event instead of keydown event and set the event as "handled" like e.Handled = true to prevent adding the new line.
KeyEventHandler keyeventHandler = new KeyEventHandler(rtbText_KeyDown);
rtbText.AddHandler(TextBox.PreviewKeyDownEvent, keyeventHandler, true);
Or based on this document, you can change how your TextBox reacts to key input by overriding Control.OnKeyDown. First, declare a custom class inherits from TextBox and override OnKeyDown event. Then you can continue to use keydown event to do something.
public class MyTextBox : TextBox
{
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down) && e.Key == VirtualKey.Enter)
{
e.Handled = true;
}
else
{
base.OnKeyDown(e);
}
}
}
.xaml:
<local:MyTextBox Width="400" AcceptsReturn="True" x:Name="rtbText"></local:MyTextBox>
I have registed ctrl+` as a hotkey,and I want to display a window when I press the hotkey and not release the leftctrl key and toggle ` key to do something else just like alt+tab switch the application.Here is the code.
private void ListOnKeyDown(object sender, KeyEventArgs e)
{
if (e.SystemKey==Key.LeftCtrl && e.Key == Key.Oem3)
{
m_host.SelectNext();
}
}
But I found this way only fired one key.So what's the right way to fire the key event?
And here is the debug information.
debug information
Just change your keydown event to detect the modifier this way
private void ListOnKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Oem3)
{
m_host.SelectNext();
e.Handled = true;
}
}
Because onKeyDown event works for ONE key only, in order to use two keys at same time you need little improvise:
bool firstkeyisOn = false;
private void ListOnKeyDown(object sender, KeyEventArgs e)
{
if (e.SystemKey==Key.LeftCtrl/*Or other key by choice*/)
{
firstkeyisOn = true;
e.Handled = true;
return;
}
if(firstkeyisOn && (e.Key == Key.Oem3/*Or other key by choice*/))
{
m_host.SelectNext();
}
}
private void ListOnKeyUp(object sender, KeyEventArgs e)
{
if (e.SystemKey==Key.LeftCtrl/*Key must be same as holding one*/)
{
firstkeyisOn = false;
}
//or
//firstkeyisOn = false;
}
To cancel hotkey mode you just add firstkeyisOn = false under OnKeyUp event and you good to go.
Hello I just started in Xamarin with an Android project and I encountered a problem on the keypress of an edittext. When the Enter is fired on my first Edittext and it gives focus to the Edittext (txtArtikel), but then the keypress of this Edittext is triggered and jumps to the third Edittext. So it skips my second Edittext with just one Enter press. Can anyone help me?
txtArtikel.KeyPress += txtArtikelPress;
private void txtArtikelPress(object sender, View.KeyEventArgs e)
{
e.Handled = false;
if (e.KeyCode == Keycode.Enter)
{
txtAantal.RequestFocus();
}
}
EDIT
I'm still working with the Keypress and now looking for an Enter and Escape. When the txtWerf is empty it jumps to txtArtikel, but when it contains text it goes to txtAantal.
private void txtWerfPress(object sender, View.KeyEventArgs e)
{
if (e.KeyCode == Keycode.Enter && e.Event.Action == KeyEventActions.Down)
{
if (txtWerf.Text.Trim() != "")
{
if (txtArtikel.RequestFocus())
e.Handled = true;
}
}
else
e.Handled = false;
}
private void txtArtikelPress(object sender, View.KeyEventArgs e)
{
if (e.KeyCode == Keycode.Enter && e.Event.Action == KeyEventActions.Down)
{
if (txtArtikel.Text.Trim() != "")
{
if (txtAantal.RequestFocus())
e.Handled = true;
}
}
else if (e.KeyCode == Keycode.Escape && e.Event.Action == KeyEventActions.Down)
{
if (txtWerf.RequestFocus())
e.Handled = true;
}
else
Scanner.CheckForScannedData(sender, ref e);
e.Handled = false;
}
private void txtAantalPress(object sender, View.KeyEventArgs e)
{
if (e.KeyCode == Keycode.Escape && e.Event.Action == KeyEventActions.Down)
{
if (txtArtikel.RequestFocus())
e.Handled = true;
}
else
e.Handled = false;
}
You don't need to handle the KeyPress event in order to set the focus to the next EditText.
Android has a good algorithm that handles the focus when editing is done.
How does the app behave on pressing enter when you remove the event handler? Does it set the focus to the correct EditText? If it focuses he wrong view then you should take a look on how to
Move to another EditText when Soft Keyboard Next is clicked on Android.
If the focus doesn't change at all then you should tell Android what to do when the user has completed his input by using android:imeOptions: http://developer.android.com/guide/topics/ui/controls/text.html#Actions.
The problem
I'm trying to get a text field to process Tab and Escape to handle a user password field. I currently have an event firing on PreviewKeyDown to allow me to catch Escape and Tab on the KeyDown event and then a KeyDown event to process it as follows:
private void passwordText_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
bool success = this.SelectNextControl(ActiveControl, true, false, true, true);
e.Handled = true;
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.Escape)
{
keepPassword = false;
bool success = this.SelectNextControl(ActiveControl, true, false, true, true);
e.Handled = true;
e.SuppressKeyPress = true;
}
else
{
e.Handled = false;
base.OnKeyDown(e);
}
}
private void passwordText_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Tab || e.KeyCode == Keys.Escape)
{
e.IsInputKey = true;
}
}
The problem I'm running into is that the SelectNextControl command returns true, but the ActiveControl does not change. It's still on the passwordText control.
Further Insight
It's calling the Leave override, and then the Enter override. If I remove Leave from the events, it correctly selects the next control. I'm posting the code from Leave here while I puzzle things through:
private void passwordText_Leave(object sender, EventArgs e)
{
if (passwordText.ReadOnly == false)
{
if (keepPassword) // This is used to handle the case of using ESC to cancel the password entry.
{
// Change user password accordingly.
password = GlobalDataStore.HashPassword(passwordText.Text);
}
else
{
keepPassword = true;
}
if (String.IsNullOrWhiteSpace(passwordText.Text))
{
passwordText.Text = "";
}
else
{
passwordText.Text = "(Hashed Password)";
}
passwordText.UseSystemPasswordChar = false;
passwordText.ReadOnly = true;
}
}
Current Workaround
I moved the guts of the Leave Event into a separate function, ProcessPasswordTextLeave(). Inside the KeyDown event, before I do the select, I remove the Leave Event, do the Select, run the ProcessPasswordTextLeave() function, then add the Leave Event again. Messy, but it works for now. I would prefer something more elegant. I'd also like to know why processing it as a Leave event restore focus to it.