I've a project where I need to focus previous field if current one is empty but user keep deleting. Like when you type CD-Key somewhere. You have couple blocks with 4-5 symbols each. And if you erase 3rd textBox for example you will be forced back to the second textBox right after 3rd one become emprty.
if (textBox2.Text.Length == 0)
{
Keyboard.Focus(textBox1);
}
This code works fine but considering that I've another onfocus event so textBox2 become empty as soon as got focus and due to code above focus forcing back to the textBox1. So it's looped.
If I get it right I need to catch pressing the Delete button, right? But here is my problem goes. I don't know how to insert this code
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
if (textBox2.Text.Length == 0)
{
Keyboard.Focus(textBox1);
}
}
}
inside this function:
private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBox2.Text.Length == 2)
{
Keyboard.Focus(textBox3);
}
// HERE I NEED SOMETHING LIKE ELSE IF (e.Key == Key.Delete) {...
}
Help me please.
UPD. I've tried one more solution but it doesn't work:
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
if (textBox2.Text.Length == 0)
{
Keyboard.Focus(textBox1);
}
}
}
Here is the generic soution for arbitrary amount of TextBox'es.
The initialization of the TextBox'es list:
private readonly List<TextBox> _textBoxes;
public MainWindow()
{
InitializeComponent();
_textBoxes = new List<TextBox> { _textBox1, _textBox2, _textBox3 };
}
The version with KeyUp event:
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Tab)
return;
var current = (TextBox)sender;
if (current.Text.Any())
return;
var index = _textBoxes.IndexOf(current);
if (index == 0)
return;
var previous = _textBoxes[index - 1];
previous.Focus();
previous.CaretIndex = previous.Text.Length;
}
The above version dissalows to jump through TextBox'es in press and hold scenario. To get around this, use TextChanged event:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var current = (TextBox)sender;
if (current.Text.Any())
return;
var index = _textBoxes.IndexOf(current);
if (index == 0)
return;
var previous = _textBoxes[index - 1];
previous.Focus();
previous.CaretIndex = previous.Text.Length;
}
Third solution with PreviewKeyDown that supports only Key.Delete:
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete)
return;
var current = (TextBox)sender;
if (current.Text.Length != 0)
return;
var index = _textBoxes.IndexOf(current);
if (index == 0)
return;
var previous = _textBoxes[index - 1];
previous.Focus();
previous.CaretIndex = 0;
}
Fourth solution also with PreviewKeyDown that supports both Key.Delete and Key.Back:
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete && e.Key != Key.Back)
return;
var current = (TextBox)sender;
if (current.Text.Length != 0)
return;
var index = _textBoxes.IndexOf(current);
if (index == 0)
return;
var previous = _textBoxes[index - 1];
previous.Focus();
if (e.Key == Key.Delete)
previous.CaretIndex = 0;
}
Finally. This one works:
private void textBox2_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
if (textBox2.Text.Length == 0)
{
Keyboard.Focus(textBox1);
}
}
}
This is not tested but should also work.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (textBox2.Text == "")
{
textBox1.Focus();
}
}
private void textBox3_KeyDown(object sender, KeyEventArgs e)
{
if (textBox3.Text == "")
{
textBox2.Focus();
}
}
}
Related
I have a datagrid with a combobox, i want to get my value, i can get it but i dont know why, i get it 4 times ???
could someone help me ?
here my code :
private void dgvLocataire_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
dgvLocataire.BeginEdit(false);
var ec = dgvLocataire.EditingControl as DataGridViewComboBoxEditingControl;
if (ec != null && ec.Width - e.X < SystemInformation.VerticalScrollBarWidth)
ec.DroppedDown = true;
if ((e.ColumnIndex != 3) && (e.ColumnIndex != 4))
{
dgvLocataire.Columns[e.ColumnIndex].ReadOnly = true;
}
dgvLocataire.CellValueChanged +=
new DataGridViewCellEventHandler(dgvLocataire_CellValueChanged);
//dgvLocataire.CurrentCellDirtyStateChanged +=
//new EventHandler(dgvLocataire_CurrentCellDirtyStateChanged);
}
private void dgvLocataire_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
dgvLocataire.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
private void dgvLocataire_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
string comboboxSelectedValue = string.Empty;
if (dgvLocataire.Columns[e.ColumnIndex].GetType() == typeof(DataGridViewComboBoxColumn))
comboboxSelectedValue = dgvLocataire.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
MessageBox.Show(comboboxSelectedValue);
}
The messagebox appears 4 times when i choose a value in combobox.
Thanks for your help
In dgvLocataire_CellMouseClick method, you are subscribing to dgvLocataire_CellValueChanged every time you click. Which means it can be called multiple times => MessageBox.Show(comboboxSelectedValue) is called multiple times.
You should subscribe to this event only once at the initialization of this form.
I change like this
private void dgvLocataire_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
dgvLocataire.BeginEdit(false);
var ec = dgvLocataire.EditingControl as DataGridViewComboBoxEditingControl;
if (ec != null && ec.Width - e.X < SystemInformation.VerticalScrollBarWidth)
ec.DroppedDown = true;
if ((e.ColumnIndex != 3) && (e.ColumnIndex != 4))
{
dgvLocataire.Columns[e.ColumnIndex].ReadOnly = true;
}
}
private void dgvLocataire_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox cb = e.Control as ComboBox;
if (cb != null)
{
cb.SelectionChangeCommitted -= new EventHandler(ComboBox_SelectedIndexChanged);
// now attach the event handler
cb.SelectionChangeCommitted += new EventHandler(ComboBox_SelectedIndexChanged);
}
}
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
string item = cb.Text;
if (item != null)
MessageBox.Show(item);
}
`
but now i dont get the messagebox to show ???
any help ?
Thanks
How to check if DataGridView cell contain number between 0 and 3 while entering value?
This is how I check if specific cell constains int number:
private void dgUpitnik_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress -= new KeyPressEventHandler(ColumnOcjena_KeyPress);
if (dgUpitnik.CurrentCell.ColumnIndex == 2) //Desired Column
{
TextBox tb = e.Control as TextBox;
if (tb != null)
{
tb.KeyPress += new KeyPressEventHandler(ColumnOcjena_KeyPress);
}
}
}
private void ColumnOcjena_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
But how to check inside KeyPress event that the number entered in cell is 0, 1, 2 or 3?
I've found solution, here it is:
private void dgUpitnik_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
dgUpitnik.Rows[e.RowIndex].ErrorText = "";
int newInteger;
if (e.ColumnIndex == 2)
{
if (dgUpitnik.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
{
if (!int.TryParse(e.FormattedValue.ToString(), out newInteger) || newInteger > 3)
{
e.Cancel = true;
dgUpitnik.Rows[e.RowIndex].ErrorText = "Ocjena mora biti u rasponu od 0 do 3!";
}
}
}
}
Maybe it will be usable for someone someday.
I am trying to disable people from deleting a textbox in a richtextbox. The project is using windows form.
Here is the code I have:
private void Form1_Load(object sender, EventArgs e)
{
richTextBox1.KeyPress += new KeyPressEventHandler(richTextBox1_KeyPress);
}
void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)8)
{
e.Handled = true;
MessageBox.Show("Try not to delete... write freely and openly");
//The msgbox shows, but the delete still happens within the form.
}
}
Does not show messagebox and does not stop the delete:
private void Form1_Load(object sender, EventArgs e)
{
richTextBox1.KeyDown += new KeyEventHandler(richTextBox1_KeyDown);
}
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
e.Handled = true;
MessageBox.Show("Delete Pressed");
// Does not show message box...
}
}
Per the MSDN documentation on KeyPressEventArgs.KeyChar, you cannot get or set the DELETE key using that event. You will need to use the KeyEventArgs.KeyCode instead, subscribing to the KeyDown and KeyUp events.
My solution:
void richTextBox1_TextChanged(object sender, EventArgs e) {
richTextBox1.SelectAll();
richTextBox1.SelectionProtected = true;
richTextBox1.Select(richTextBox1.Text.Length, 0);
}
Side note: yes, this will flicker. Proof of concept only. To avoid the flicker, see How to append text to RichTextBox without scrolling and losing selection?
Instead Of KeyPress event use KeyDown In RichText Box.
try this to prevent from deleting text in RichText Box
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 46)
e.Handled = true;
}
If you want to disallow both delete and backspace You Can Change KeyDown Event as follows
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 8 || e.KeyValue == 46)
e.Handled = true;
}
You must add Back key to prevent delete :
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
{
e.Handled = true;
MessageBox.Show("Delete Pressed");
// Does not show message box...
}
}
Edit:
Non-selectable RichTextBox :
public class ViewOnlyRichTextBox : System.Windows.Forms.RichTextBox {
// constants for the message sending
const int WM_SETFOCUS = 0x0007;
const int WM_KILLFOCUS = 0x0008;
protected override void WndProc(ref Message m) {
if(m.Msg == WM_SETFOCUS) m.Msg = WM_KILLFOCUS;
base.WndProc (ref m);
}
}
My solution is some kind of the combination of SerkanOzvatan's and LarsTech's answers. Here is the code:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
{
e.Handled = true;
MessageBox.Show("Try not to delete... write freely and openly");
// Does not show message box...
}
}
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
richTextBox1.SelectionProtected = richTextBox1.SelectionLength > 0;
}
It works great :)
And here is another solution of my own which also works great, especially if you want to do with a TextBox (not a RichTextBox), it doesn't have a SelectionProtected, and this is used OK for both TextBox and RichTextBox (just change the class name in the following code accordingly):
public class WritableRichTextBox : RichTextBox
{
protected override bool ProcessKeyMessage(ref Message m)
{
int virtualKey = m.WParam.ToInt32();
if (SelectionLength > 0 || virtualKey == 0x08 || virtualKey == 0x2e)
{
if (virtualKey != 0x25 && virtualKey != 0x26 && virtualKey != 0x27 && virtualKey != 0x28)
return true;
}
return base.ProcessKeyMessage(ref m);
}
}
I need to have a text box on which events of Delete and Backspace works.Is it possible to have such a text box in C#,or restrict the behavior of text box in such a way. Other keys do not work.
Use TextBox.KeyPress event:
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back)
{
// your stuff
}
e.Handled = true;
}
For winforms you can do it like this:
protected void myTextBox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
e.Handled = !IsValidCharacter(e.KeyChar);
}
private bool IsValidCharacter(Keys c)
{
bool isValid = false;
if (c == Keys.Space)
{
isValid = true;
}
return isValid;
}
If you want delete key works ..
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
Keys k = e.KeyCode
If Not (k = Keys.Back Or k = Keys.Delete)
{
e.Handled = True
}
}
I have a lot of textboxes. I have a button that will cut the selected text of the Focused textbox. How do i do that? I have tried this:
if (((TextBox)(pictureBox1.Controls[0])).SelectionLength > 0)
{
((TextBox)(pictureBox1.Controls[0])).Cut();
}
Hope it is WinForms
var textboxes = (from textbox in this.Controls.OfType<TextBox>()
where textbox.SelectedText != string.Empty
select textbox).FirstOrDefault();
if (textboxes != null)
{
textboxes.Cut();
}
Loop through the controls to find the one with selected text:
foreach (Control x in this.PictureBox1.Controls)
{
if (x is TextBox)
{
if (((TextBox)x).SelectionLength > 0)
{
((TextBox)(x).Cut(); // Or some other method to get the text.
}
}
}
Hope this helps!
Try using common Enter and Leave events to set the last TextBox that had Focus.
private void textBox_Enter(object sender, EventArgs e)
{
focusedTextBox = null;
}
private void textBox_Leave(object sender, EventArgs e)
{
focusedTextBox = (TextBox)sender;
}
private void button1_Click(object sender, EventArgs e)
{
if (!(focusedTextBox == null))
{
if (focusedTextBox.SelectionLength > 0)
{
Clipboard.SetText(focusedTextBox.SelectedText);
focusedTextBox.SelectedText = "";
focusedTextBox = null;
}
}
}