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();
}
}
Related
I would like to validate that a DataGridView column only accepts integers.
I used the Keypress event, but this event was not fired on pressing a key.
Here's the code I used
private void dgvSaleReturnWintoutInvoice_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress -= new KeyPressEventHandler(dgvSaleReturnWintoutInvoice_KeyPress);
if (dgvSaleReturnWintoutInvoice.Columns["dgvReturnQTY"].Index == dgvReturnQTY.Index)
{
TextBox tbt = e.Control as TextBox;
if (tbt != null)
{
tbt.KeyPress += new KeyPressEventHandler(dgvSaleReturnWintoutInvoice_KeyPress);
}
}
}
private void dgvSaleReturnWintoutInvoice_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
Your code works for me, though the way I detected the current column differs:
if (someDataGridView.CurrentCell.OwningColumn == someDataGridView.Columns["someColumn"])
I would also point out that your code doesn't prevent someone pasting alpha text into the box
When I click on my ListView and write "this text!", I want my Label (or TextBox if that's easier) to change text to "this text!".
How can I do this?
You can use the AfterLabelEdit event:
private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
yourLabel.Text = e.Label;
}
Don't forget to hook up the event!
If you want to display the new text while typing you can either try to listen to the keyboard between the BeforeLabelEdit and AfterLabelEdit events or you can overlay your own TextBox and use its TextChanged event.
I think this is easier but if you want to do special things, like disallowing editing key etc, it will alway mean some extra work!
Here is a short example how to overlay a TextBox over the Item:
TextBox EditCell = new TextBox();
public Form1()
{
InitializeComponent();
//..
EditCell.TextChanged += EditCell_TextChanged;
EditCell.Leave += EditCell_Leave;
EditCell.KeyDown += EditCell_KeyDown;
}
void EditCell_TextChanged(object sender, EventArgs e)
{
yourLabel.Text = EditCell.Text;
}
void EditCell_Leave(object sender, EventArgs e)
{
ListViewItem lvi = EditCell.Tag as ListViewItem;
if (lvi != null) lvi.Text = EditCell.Text;
EditCell.Hide();
}
void EditCell_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
EditCell_Leave(null, null);
}
else if (e.KeyCode == Keys.Escape)
{
e.Handled = true;
EditCell.Tag = null;
EditCell_Leave(null, null);
}
e.Handled = false;
}
private void listView1_BeforeLabelEdit(object sender, LabelEditEventArgs e)
{
// stop editing the item!
e.CancelEdit = true;
ListViewItem lvi = listView1.Items[e.Item];
EditCell.Parent = listView1;
EditCell.Tag = lvi;
EditCell.Bounds = lvi.Bounds;
EditCell.BackColor = Color.WhiteSmoke; // suit your taste!
EditCell.Text = lvi.Text;
EditCell.Show();
EditCell.SelectionStart = 0;
EditCell.Focus();
EditCell.Multiline = true; // needed to allow enter key
}
The above code works fine but as our chat has established that you actually only want to grab keyboard input and direct it to a Label, here is the much, much simpler solution to the 'hidden' problem..:
Start by setting your Forms's KeyPreview totrue. Then hook up the KeyPressed event of the Form:
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (ActiveControl == listView1)
{
e.Handled = true; // needed to prevent an error beep
yourLabel.Text += e.KeyChar.ToString();
}
}
This will not allow any editing and only let the label text grow. You may want to expand with a few extras, like coding for Backspace, if you like..:
if (e.KeyChar == (char)Keys.Back && yourLabel.Text.Length > 0)
yourLabel.Text = yourLabel.Text.Substring(0, yourLabel.Text.Length - 1);
else yourLabel.Text += e.KeyChar.ToString();
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();
}
}
related to this topic:
Hidden ListBox will appear while Typing Words in RichTextBox
im working on a code editor and i just want to know if how can I add items from listbox to textbox using enterkey .
further more heres my strings:
public String[] ab = { "abstract" };
public String[] am = { "AmbientProperties", "AmbientValueAttribute" };
sample:
in richtextbox (rtb) , i type Ab, then hiddenlistbox will appear with "abstract" text on it (already do that) using this code:
if (token == "letterA" || token.StartsWith("Ab") || token.StartsWith("ab"))
{
int length = line.Length - (index - start);
string commentText = rtb.Text.Substring(index, length);
rtb.SelectionStart = index;
rtb.SelectionLength = length;
lb.Visible = true;
KeyWord keywordsHint = new KeyWord();
foreach (string str in keywordsHint.ab)
{
lb.Items.Add(str);
}
break;
}
then after that after i press enterkey i want to add the abstract from listbox to the richtextbox .
RichTextBox declared as rtb and ListBox declared as lb
what should i do? thanks .
Certain controls do not recognize some keys when they are pressed in key down event.
For eg ListBox do not recognize if key pressed is Enter Key.
Please see remarks section in following link -
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keydown(v=vs.110).aspx
one of the solution for your problem can be
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown(v=vs.110).aspx
implement PreviewKeyDown Event for your listbox for listbox to recognize your actions.
Here is sample code snippet -
private void listBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
//Do your task here :)
}
}
private void listBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Enter:
e.IsInputKey = true;
break;
}
}
You cannot directly type text to a listbox, so I created a example with textBox:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
this.richTextBox1.AppendText((sender as TextBox).Text);
e.Handled = true;
}
}
If you meant comboBox you can easily adjust this, replace line above:
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
this.richTextBox1.AppendText((sender as ComboBox).Text);
e.Handled = true;
}
}
Copy selected listbox entries to rtf box:
private void listBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
foreach (string s in listBox1.SelectedItems)
{
this.richTextBox1.AppendText(s + Environment.NewLine);
}
e.Handled = true;
}
}
I have a lot of TextBoxes in my single winform application. I am looking for a way to bind a single event method to all those textboxes when the form loads or in its constructor, so I dont add the event to every single textbox in designer.
In the event, I want to detect the ENTER key and then programmatically click on a button:
private void ApplyFilterOnEnterKey(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnApplyFilters_Click(this, null);
}
}
Now the problem is how can I loop over all textboxes in my form and bind them to the above method? My textboxes are everywhere, inside nested tablelayoutpanels or nested normal pannels. How this loop will look like and where should I put it? In form constructor or in load event?!
Instead of subscribing to every TextBox's KeyDown event, you have two other options that I think are better:
Set your button as the default button of the form by setting AcceptButton property of the form to the button you want to be clicked by pressing Enter key.
Override ProcessDialogKey on your form and check for pressing the Enter key:
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Enter)
{
// ... do what you want
return true;
}
else
return base.ProcessDialogKey(keyData);
}
Just use the Controls collection and look if the control is a textbox then append the event
Loop through all textboxes (including nested) like this as shown here: Loop through Textboxes
Then,
var allTextBoxes = this.GetChildControls<TextBox>();
foreach (TextBox tb in this.GetChildControls<TextBox>())
{
tb.Click += ApplyFilterOnEnterKey;
}
private void TextBoxFocusIn(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Text == "Encrypted value here...")
{
textBox.Text = "";
textBox.ForeColor = Color.Black;
}
}
private void TextBoxFocusOut(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Text =="")
{
textBox.Text = "Encrypted value here...";
textBox.ForeColor = Color.Gray;
}
}
private void BindPlaceHolderInTextbox(Panel contentPanel)
{
foreach(Control control in contentPanel.Controls)
{
if(control.GetType() == typeof(TextBox))
{
control.Text = "Encrypted value here...";
control.ForeColor = Color.Gray;
control.GotFocus += new System.EventHandler(TextBoxFocusIn);
control.LostFocus += new System.EventHandler(TextBoxFocusOut);
}
}
}