Quote:
Dave K. wrote: "By using ENTER to move from field to field, you are going against the standard functionality of Windows applications."
I respectfully disagree with this statement in the sense that I think it is too generalized, too absolute.
There are many scenarios where an application controls the focus of user interaction from Control to Control according to some set of rules, or, in sequential order. A "wizard" is a good example.
The designers of Windows Forms allow any Control to be removed from being a
TabStop by simply setting a property. For TextBox and RichTextBox, both offer Control over whether Tabs are accepted, and the TextBox allows you to ignore Enter.
These options, I believe, are there for a reason: to enable developers to have flexibility for designing application behavior.
Now, let me show you a fairly complete sketch (that means it works in VS 2017) for a WinForm UserControl that manages the users data entry in sequence through six TextBoxes. This UserControl has two Buttons, 'btnSubmit, and 'btnCancel..
All Controls in the UserControl have their TabStop property set to 'false. The TextBoxes have both AcceptsTab, and AcceptsReturn properties set to false.
All key-entry on the UserControl is intercepted by over-riding ProcessCmdKey.
Validators are attached to the first three TextBoxes: the first requires at least one digit to complete; the second requires 2 digits and 2 punctuations to complete; the third requires some text entry of any type. The other three TextBoxes have a default validator defined that accepts anything, or no text.
When the user reaches the last TextBox, if there is no validation error, the Submit Button is enabled.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace MatrixTestForm
{
public partial class DataEntryUserControl : UserControl
{
public DataEntryUserControl()
{
InitializeComponent();
}
public Action<List<string>> SendData;
public Dictionary<TextBox,Func<TextBox, bool>> TxtBxesToValidator = new Dictionary<TextBox, Func<TextBox, Boolean>>();
private bool allValid = false;
private List<TextBox> textBoxes = new List<TextBox>();
private TextBox activeTextBox;
private int lastTBoxIndex;
private void DataEntryUserControl_Load(object sender, EventArgs e)
{
btnSubmit.Enabled = false;
textBoxes.AddRange(new List<TextBox>()
{
textBox1, textBox2, textBox3, textBox4, textBox5, textBox6
});
lastTBoxIndex = textBoxes.Count - 1;
foreach (var tbx in textBoxes)
{
tbx.Enter += TbxOnEnter;
tbx.Leave += TbxOnLeave;
}
activeTextBox = textBox1;
textBox1.Capture = true;
toolTip1.SetToolTip(textBox1, "no digits");
TxtBxesToValidator[textBox1] = box =>
{
return box.Text != null && !box.Text.Any(char.IsDigit);
};
toolTip1.SetToolTip(textBox2,"2 digits, 2 ounctuation");
TxtBxesToValidator[textBox2] = box =>
{
return box.Text != null
&& box.Text.Any(char.IsDigit)
&& box.Text.Where(char.IsDigit).Count() == 2
&& box.Text.Any(char.IsPunctuation)
&& box.Text.Where(char.IsPunctuation).Count() == 2;
};
toolTip1.SetToolTip(textBox3, "enter something");
TxtBxesToValidator[textBox3] = box =>
{
return !String.IsNullOrWhiteSpace(box.Text);
};
}
private void TbxOnEnter(Object sender, EventArgs eventArgs)
{
activeTextBox = sender as TextBox;
activeTextBox.Capture = true;
}
private void TbxOnLeave(Object sender, EventArgs eventArgs)
{
activeTextBox.Capture = false;
activeTextBox = null;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter && activeTextBox != null)
{
activeTextBox.Capture = false;
if (TxtBxesToValidator.ContainsKey(activeTextBox))
{
allValid = TxtBxesToValidator[activeTextBox](activeTextBox);
}
if (! allValid)
{
btnSubmit.Enabled = false;
MessageBox.Show("invalid");
return base.ProcessCmdKey(ref msg, keyData);
}
int ndx = textBoxes.IndexOf(activeTextBox);
if (ndx == lastTBoxIndex)
{
btnSubmit.Enabled = allValid;
}
else
{
textBoxes[ndx + 1].Focus();
textBoxes[ndx + 1].Capture = true;
}
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void btnCancel_Click(object sender, EventArgs e)
{
btnSubmit.Enabled = false;
}
private void btnSubmit_Click(object sender, EventArgs e)
{
SendData?.Invoke(textBoxes.Select(tbx => tbx.Text).ToList());
}
}
}