I have this code for window form application and I have been attempting to convert it to a Silverlight application but it does not work!. There is a Textbox and I attached KeyDown event handler to it. when the user press the arrow key ( left or right) while the focus on the textbox, it will write . or -. When it is window form i used e.KeyCode and Keys.Right and its works great but when it is silverlight I used e.Key and key.Right and the program doesn't work good because the arrows do the 2 functions moving and write ./-. How I can work this out in Silverlight?
(My English not good)
The code ( window form):
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (sender is TextBox)
{
TextBox textBox = (TextBox)sender;
if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
{
e.Handled = true;
char insert;
if (e.KeyCode == Keys.Left)
{ insert = '.'; }
else
{ insert = '-'; }
int i = textBox.SelectionStart;
textBox.Text = textBox.Text.Insert(i, insert.ToString());
textBox.Select(i + 1, 0);
}
}
}
(and Silverlight):
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (sender is TextBox)
{
TextBox textBox = (TextBox)sender;
if (e.Key == Key.Left || e.Key == Key.Right)
{
e.Handled = true;
char insert;
if (e.Key == Key.Left)
{ insert = '.'; }
else
{ insert = '-'; }
int i = textBox.SelectionStart;
textBox.Text = textBox.Text.Insert(i, insert.ToString());
textBox.Select(i + 1, 0);
}
}
}
I don't understand, is there huge different effect between using Keycode/Keys and Key/Key or because something else?
The KeyDown event will not proportionate for several keys in TextBox, as TextBox uses those keys internally and marks those as e.Handled before they get to custom user code.
Here is the MSDN quote that explains the issue further:
Another example is TextBox. Some keys
such as the ARROW keys are not
considered text by TextBox and are
instead considered specific to the
control UI behavior, and the TextBox
marks these event cases as handled.
If I were you, I'd just use the KeyUp event as your custom code does appear to work fine in that event.
Sincerely,
-- Justin Angel
You have to set
e.Handled = true;
so the event won't be consumed further down the route.
Related
This question already has an answer here:
Textbox multiline ability without adding a newline
(1 answer)
Closed 1 year ago.
I have a text editing application in WPF C#, in which I need to add a new line when the user presses the CTRL + ENTER combination and perform another operation when the user presses the ENTER key. I tried using the following code in the Keydown event, but the line is added when ENTER is pressed and not added when CTRL + ENTER is pressed. Any help is most welcome. Thanks.
private void rtbText_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.LeftCtrl) || e.KeyboardDevice.IsKeyDown(Key.RightCtrl))
{
switch (e.Key)
{
case Key.Enter: break;
}
}
else
{
if (e.Key == Key.Enter)
{
btnFormat_Click(this, null);
e.Handled = true;
}
}
}
You can achieve this using PreviewKeydown event. When we detect Ctrl+Enter we add a new line to the text and move the caret to the end.
private void rtbText_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.LeftCtrl) || e.KeyboardDevice.IsKeyDown(Key.RightCtrl))
{
switch (e.Key)
{
case Key.Enter:
TextBox t = sender as TextBox;
t.Text += Environment.NewLine;
t.CaretIndex = t.Text.Length - 1;
break;
}
}
else
{
if (e.Key == Key.Enter)
{
btnFormat_Click(this, null);
e.Handled = true;
}
}
}
I'm a newbee to C# and I'm trying to write code in Visual Studio. I need your help.
I want to enter numbers to 20pcs textbox in tabpage1 in form by hand held barcode scanner in C#. Cursor must go to next textbox after reading from barcode scanner. And I will check the read data with some conditions (between 2 values numbers etc) for every textbox.
I write some code but it makes code size big. I think it must be easy way I need your comment and help.
The barcode scanner reads the barcode and sends barcode number + enter code. And barcode scanner read and put number to first textbox then pass to next textbox and it repeating for all textbox - how can I do this easily?
Thanks
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
textBox1.SelectAll();
textBox2.Focus();
e.Handled = true;
}
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
textBox2.SelectAll();
textBox3.Focus();
e.Handled = true;
}
}
.
.
.
.
private void textBox20_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
textBox20.SelectAll();
textBox1.Focus();
e.Handled = true;
}
}
The good news is that the sender object is always that control which has triggered the event. In other words the sender is a reference to one of your TextBoxs.
You can take advantage of this fact and you can have a single event handler, which could be reused for multiple events.
private void textBoxN_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
var textBoxCurrent = sender as TextBox;
textBoxCurrent.SelectAll();
//TODO: set focus for next
e.Handled = true;
}
}
So, the next question is how to get a reference to the next TextBox?
You can use the Tag property for this.
In case of WinForms the Control object has a property called Tag.
In case of WPF the FrameworkElement object has a property called Tag.
In both cases this property is an object so we can store anything in that. If we populate that with a reference to the next TextBox then the generic handler would look like this:
private void textBoxN_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
var textBoxCurrent = sender as TextBox;
textBoxCurrent.SelectAll();
var textBoxNext = textBoxCurrent.Tag as TextBox;
textBoxNext.Focus();
e.Handled = true;
}
}
What's left?
Populate the Tag properties
Subscribe to the KeyDown events
private void Init()
{
var textBoxes = new List<TextBox> { TextBox1, TextBox2, ..., TextBox20 };
foreach(var item in textBoxes.Select((textBox, index) => (textBox, index))
{
var nextIdx = (item.index + 1) % textBoxes.Count;
item.textBox.Tag = textBoxes[nextIdx];
item.textBox.KeyDown += textBoxN_KeyDown;
}
}
We have created an iterator here which is deconstructed into a textbox and an index of this TextBox in the textBoxes collection.
We have calculated the next TextBox index into the nextIdx. Then we have wired up everything.
here is an idea for solving
class Program
{
LinkedList<TextBox> _textBoxes;
ctor()
{
_textBoxes = new LinkedList<TextBox>();
_textBoxes.List.AddLast(textbox1);
_textBoxes.List.AddLast(textbox20);
}
private void textBox_KeyDown_justOneCommonHandle(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
var textboxCurrent = _textBoxes.Current;
// make sure that Value is the sender
textboxCurrent.SelectAll();
_textBoxes.MoveNext();
var textboxNext = _textBoxes.Current;
// check the end of list
textboxNext.Focus();
e.Handled = true;
}
}
}
# Peter Csala, #Ivan Stavenchuk
Thanks for your idea and help. I solved my problem as shown below
I added a main Textbox (textBox21) and used keydown event of main textbox
private void textBox21_KeyDown(object sender, KeyEventArgs e)
{
TextBox tb = new TextBox();
tb.Name = "textBox" + i.ToString();
if (e.KeyCode==Keys.Enter)
{
TextBox tbx = this.Controls.Find(tb.Name, true).FirstOrDefault() as TextBox;
tbx.Text = textBox21.Text ;
i++;
if (i>20) i=1;
textBox21.SelectAll();
}
}
I dynamically created a Listbox and filled it with some items, Upon typing a dot in a Textbox i want to show the Listbox so that the user can select any item by using arrow keys .
I did everything up to this point. When the user types a dot in the Textbox, The Listbox gets shown, But the arrow keys wont select any items!
private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
string[] words= ((TextBox)sender).Text.Split(' ');
string s = sampleWord.Text = words[words.Length - 1];
if (e.KeyCode == Keys.OemPeriod)
{
ShowPopUpList(s);
}
else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up)
{
lst.Focus();//doesnt work :-/
}
else
{
lst.Hide();
txtResults.Focus();
}
}
This is the code for creating the listbox on FormLoad()
private void CreateListBox()
{
lst = new ListBox();
lst.Size = new Size(70, 130);
lst.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
lst.KeyDown += lst_KeyDown;
lst.DoubleClick += lst_DoubleClick;
//adding some test input
lst.Items.Add("بسم");
lst.Items.Add("الله ");
lst.Items.Add("الرحمن ");
lst.Items.Add("الرحیم ");
lst.Items.Add("بنام ");
lst.Items.Add("خداوند ");
lst.Items.Add("بخشنده ");
lst.Items.Add("مهربان ");
lst.Items.Add("الهی شکرت ");
}
private void ShowListbox()
{
txtResults.SelectionStart = txtResults.Text.Length;
txtResults.SelectionLength = 0;
Point index = txtResults.GetPositionFromCharIndex(txtResults.SelectionStart-1);
lst.Location = new Point (index.X-50, index.Y+70);
this.Controls.Add(lst);
lst.BringToFront();
lst.Show();
}
In ShowPopUpList(s) the ShowListbox() method is called. nothing fancy about it!
Note:
I only need the list box to get focus when i use UP or DOWN arrow keys to explicitly select an item. unless then i need to be able to freely continue typing and dont lose focus to listbox.
Whats the way around doing it ?
Remove focus from the textbox keydown handler and place it here:
private void ShowPopUpList(string s)
{
//your initialization of the
//listbox here and after..
listBox1.Focus();
}
Another way:
if (e.KeyCode == Keys.OemPeriod)
{
ShowPopUpList(s);
listBox1.Focus();
}
The real big difference is it gets focus rightaway.with your old code would first check the keydown and on the second hit it would already contain the focus.
Final Edit:
If Listbox needs to get the focus on up/down arrow keys(and only with those keys):
if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up)
{
ShowPopUpList();
listBox1.Focus();
listBox1.SelectedIndex = 0;
}
This worked just fine and dandy for me :)
ListBox lb;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Contains("."))
{
lb = new ListBox();
lb.Location = textBox1.Location;
this.Controls.Add(lb);
lb.Items.Add("Item 1");
lb.Items.Add("Item 2");
lb.Items.Add("Item 3");
lb.Show();
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
lb.Focus();
}
}
I have previously asked a question on how to Selecting dynamically created Listboxs items in C# which was answered. The problem now is that when the listbox gets the focus when popped up! I can't continue typing unless I either select an item or press Esc, which I have explicitly defined to set focus back to my TextBox.
The irony is that I have a condition in my KeyDown event which says if the UP or Down arrow keys are pressed, set the focus on ListBox so that user can choose an item, but don't transfer the focus so that user can continue typing freely.
Just like what we have on Visual Studio, when a user presses a dot, he is not blocked and forced to choose an item form the Intellisense list, but he can continue typing and or at any time use arrow keys UP or Down to select the proper item.
I can't achieve the same functionality using the code below. How can I get this to work as mentioned?
I need to say that using ActiveControl, and transferFocus, using this.Focus() prior to lst.Focus(), disabling and enabling textbox they all didn't work!
private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
string[] words= ((TextBox)sender).Text.Split(' ');
string s = sampleWord.Text = words[words.Length - 1];
if (e.KeyCode == Keys.OemPeriod)
{
ShowPopUpList(s);
lst.Focus(); //This transfers the focus to listbox but then prevents user
//from being able to type anymore unless he/she chooses an item!
}
else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up)
{
lst.Focus();//doesnt work :-/
}
else
{
lst.Hide();
txtResults.Focus();
}
}
This behavior is happening because you are shifting focus to the listbox. Try thinking about it differently and instead of giving focus to the listbox, select the next/previous item in the list when the up or down arrows are pressed.
change your "else if" to the following:
else if (e.KeyCode == Keys.Down)
{
if (lst.SelectedIndex + 1 < lst.Items.Count)
{
lst.SelectedIndex += 1;
}
e.Handled = true;
}
else if (e.KeyCode == Keys.Up)
{
if (lst.SelectedIndex - 1 >= 0)
{
lst.SelectedIndex -= 1;
}
e.Handled = true;
}
If you want the user to be able to continue typing in the textbox while still manipulating the selection of the listbox, then you will have to fake it: don't actually set focus to the listbox when you show it. Instead, change the selection of the listbox manually in the KeyDown event for the textbox. Something like this:
private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
string[] words = ((TextBox)sender).Text.Split(' ');
string s = sampleWord.Text = words[words.Length - 1];
if (e.KeyCode == Keys.OemPeriod)
{
ShowPopUpList(s);
lst.SelectedIndex = 0;
}
else if (lst.Visible && e.KeyCode == Keys.Up)
{
// manipulate the selection on the listbox (move up)
if (lst.SelectedIndex > 0)
lst.SelectedIndex -= 1;
// eat the keypress so it textbox doesn't get it and move the cursor
e.Handled = true;
}
else if (lst.Visible && e.KeyCode == Keys.Down)
{
// manipulate the selection on the listbox (move down)
if (lst.SelectedIndex < lst.Items.Count - 1)
lst.SelectedIndex += 1;
// eat the keypress so it textbox doesn't get it and move the cursor
e.Handled = true;
}
else if (lst.Visible && e.KeyCode == Keys.Enter)
{
// insert current list box selection into text box and hide the list
txtResults.Text += lst.SelectedItem;
txtResults.SelectionStart = txtResults.Text.Length;
lst.Hide();
// eat the keypress to prevent the textbox (and the form) from acting on it
e.SuppressKeyPress = true;
e.Handled = true;
}
else
{
lst.Hide();
}
}
You don't need to focus your ListBox to allow your user to select its item using Arrow keys, your TextBox should always be focused, You have to process the Enter right in the KeyDown event handler of your TextBox, add the selected item there not in the KeyDown event handler of your ListBox, something like this:
private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
string[] words= ((TextBox)sender).Text.Split(' ');
string s = sampleWord.Text = words[words.Length - 1];
if (e.KeyCode == Keys.OemPeriod)
{
ShowPopUpList(s);//Show your ListBox without needing to focus it.
}
if(lst.Visible){
if(e.KeyCode == Keys.Down){
lst.SelectedIndex = (lst.SelectedIndex + 1) % lst.Items.Count;
}
else if (e.KeyCode == Keys.Up){
lst.SelectedIndex = lst.SelectedIndex == 0 ? lst.Items.Count - 1 : lst.SelectedIndex - 1
}
else if (e.KeyCode == Keys.Enter){//Add the selected Item
//Add the selected Item here not in the KeyDown event handler of your ListBox
//.........
//.........
//Your TextBox may not need to handle the Enter, so just suppress it after adding the selected item
e.Handled = true;
}
else
{
lst.Hide();
}
}
}
I have a simple form by which I take input:
12 Buttons, 1 Textbox (disabled & read-only)
this is what I do to handle input
Login_KeyDown() is common method I call for all the KeyDown of every UI component & the form itself..
private void Login_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
Application.Exit();
}
else if (e.KeyCode == Keys.NumPad9 || e.KeyCode == Keys.D9)
{
button3.BackgroundImage = Properties.Resources.button_hover;
button3.ForeColor = Color.White;
pin.Text = pin.Text + "9";
}
else if (e.KeyCode == Keys.Back)
{
button11.BackgroundImage = Properties.Resources.button_hover;
button11.ForeColor = Color.White;
if (pin.Text.Length > 0)
pin.Text = pin.Text.Substring(0, pin.Text.Length - 1);
}
else if (e.KeyCode == Keys.Enter)
{
MessageBox.Show(pin.Text);
}
}
This code works fine when I start the app but after I have clicked on any component, rest of the code works fine but "Enter Key Condition" doesn't work.
My guess is as "Enter Key Condition" is not working for UI components or something like that.
I have also tried using "Key Press Event" which uses KeyPressEventArgs then checking KeyChar == 13 but that is also not working.
What is the problem, and how can I solve it?
p.s.
I have not set any button click events for any button, the app is 100% KBoard based.
Check out PreviewKeyDown. Return raises that event on button controls.
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Return)
MessageBox.Show("I found return");
}
Or alternatively you can force it to raise those special keys in the KeyDown Event by using:
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Return)
e.IsInputKey = true;
}
More information: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx
Have you tried to use
Keys.Return
Instead
Edit:
Just thought of this. Do you have the acceptbutton set for the main form?
This is because your Form has AcceptButton defined. For example, you have a "OK", "Accept" or "Confirm" button with DialogResult set to "OK". This tells its parent form that there is an AcceptButton, and the Enter event on the form would go to this button.
What you should do is to catch the Enter key at form level. Add this code to the form:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((this.ActiveControl == myTextBox) && (keyData == Keys.Return))
{
//do something
return true;
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
}