TextBox Validation in Visual Studio C# - c#

I am fairly new to Visual Studio and C# in general but basically I need to check that the contents of the textbox are valid before proceeding to add the contents to a list with a button.
I am using the following objects:
A TexBox to enter the value
A Validating event linked to the TextBox to validate the data.
A Button to take action
A Click event associated to the button.
The problem is that I cannot check if the values in the box are valid or not and prevent the click event in the button to happen. In other words if the contents are not valid then do not take action.
This is my code.
public partial class mainForm : Form
{
public mainForm()
{
InitializeComponent();
}
private void addButton_Click(object sender, EventArgs e)
{
// I need to check if the content is valid before adding it to the form
ListViewItem item = new ListViewItem(this.nameTextBox.Text);
this.listView1.Items.Add(item);
}
private void nameTextBox_Validating(object sender, CancelEventArgs e)
{
int maxCharacters = 15;
String err = "";
String contents = this.nameTextBox.Text;
if (contents.Length == 0)
{
err = "I am sorry but the name cannot be empty";
e.Cancel = true;
}
else if (!contents.Replace(" ", "").Equals(contents, StringComparison.OrdinalIgnoreCase))
{
err = "I am sorry but the name cannot contain spaces";
e.Cancel = true;
}
else if (contents.Length > 15)
{
err = "I am sorry, but the name cannot have more than " + maxCharacters + " characters";
e.Cancel = true;
}
this.mainFormErrorProvider.SetError(this.nameTextBox, err);
}
}

You are confused about when the "name" text boxes' validation method is called.
See here
When you change the focus by using the keyboard (TAB, SHIFT+TAB, and so on), by calling the Selector SelectNextControl methods, or by setting the ContainerControl.ActiveControl property to the current form, focus events occur in the following order...
So clicking the button has nothing to do with the validation of the text box.
What you need to do is put the validation logic in a separate method, and then call it from both events.
Also, since you're new to C# here are some pointers.
Namespaces, Classes, methods, and properties are supposed to be Pascal Case.
Instead of using a long winded work around like this
!contents.Replace(" ", "").Equals(nameText, StringComparison.OrdinalIgnoreCase)
You could simply use
contents.Contains(" ")
There are tons of useful methods just like that, so in the future you should do more research on what you need before implementing something yourself, especially if it seems like a commonly used technique.
Also, you want to avoid if/else's as much as possible in favour of returning early.
Here's what your class might look with better practice in mind
const int NAME_MAX_CHARACTERS = 15;
public mainForm()
{
InitializeComponent();
}
private void addButton_Click(object sender, EventArgs e)
{
if(!Validate())
{
return;
}
// I need to check if the content is valid before adding it to the form
ListViewItem item = new ListViewItem(this.nameTextBox.Text);
this.listView1.Items.Add(item);
}
private void nameTextBox_Validating(object sender, CancelEventArgs e)
{
e.Cancel = !Validate();
}
private bool Validate()
{
string nameText = nameTextBox.Text;
if(String.IsNullOrEmpty(nameText))
{
this.mainFormErrorProvider.SetError(this.nameTextBox, "I am sorry but the name cannot be empty");
return false;
}
if(nameText.Contains(" "))
{
this.mainFormErrorProvider.SetError(this.nameTextBox, "I am sorry but the name cannot contain spaces");
return false;
}
if (nameText.Length > 15)
{
this.mainFormErrorProvider.SetError(this.nameTextBox, "I am sorry, but the name cannot have more than " + NAME_MAX_CHARACTERS + " characters");
return false;
}
return true;
}

Related

updating a textbox from another form. C#

I have looked at various answers, i have googled my nut off for a good few hours now, and still cant seem to get this to work.
I am trying to update a textbox on a form. i have simplified the code i am using in the hope that it was just something i was adding unnecessarily, but still cant get it to work.
I know the text is being passed to the textbox and stored in the box, but it will not display in the actual box.
In form one (Form_DMM);
private void BtnTest_Click(object sender, EventArgs e)
{
ErrorHandling EH = new ErrorHandling();
EH.updatetbtest();
}
in separate class;
public void updatetbtest()
{
string FailedMessagePB = "Test Message" + "\n";
Form_DMM FormDMM = new Form_DMM();
FormDMM.TextBoxAppend(FailedMessagePB);
FormDMM.TextBoxAppend2 = FailedMessagePB;
FormDMM = null;
}
passed back to form one;
public void TextBoxAppend(string WriteMessage)
{
TB_Issues.AppendText(WriteMessage + "\n");
System.Windows.Forms.Application.DoEvents();
TB_Issues.Invalidate();
TB_Issues.Update();
TB_Issues.Refresh();
MessageBox.Show(TB_Issues.Text);
}
public string TextBoxAppend2
{
get
{
return TB_Issues.Text;
}
set
{
TB_Issues.Text = TB_Issues.Text + value + "\n";
System.Windows.Forms.Application.DoEvents();
TB_Issues.Invalidate();
TB_Issues.Update();
TB_Issues.Refresh();
MessageBox.Show(TB_Issues.Text);
}
}
As you can see i have two separate attempts at updating the textbox, neither of which will display the test message in the textbox, but the messagebox that pops up will show the test message. it will even show the double test message from the TB_Issues.AppendText().
Can someone please help and tell me where i'm going wrong. This is driving me insane!
you can use like this
public void updatetbtest(Form_DMM FormDMM)
{
string FailedMessagePB = "Test Message" + "\n";
FormDMM.TextBoxAppend(FailedMessagePB);
FormDMM.TextBoxAppend2 = FailedMessagePB;
}
and in your buttontest_Click
private void BtnTest_Click(object sender, EventArgs e)
{
ErrorHandling EH = new ErrorHandling();
EH.updatetbtest(this);
}
From the problem posted the error is in the ErrorHandling class.
In the method updatetbtest you create a new Insance of the form object. So you create a separate form object, change the text and then you lose any reference because you set the variable to null. The message box is displayed because the TextBoxAppend method is called and the messagebox is a separate instance. The new instance you create is never displayed.
You have to hand over your calling form instance to the updatetbtest method.
Something like this:
private void BtnTest_Click(object sender, EventArgs e)
{
ErrorHandling EH = new ErrorHandling();
EH.updatetbtest(this);
}
public void updatetbtest(Form_DMM form)
{
string FailedMessagePB = "Test Message" + "\n";
form.TextBoxAppend(FailedMessagePB);
}
You try to create new form. But you must use existing.
You can pass existing form calling EH.updatetbtest(this);
And of course adding parameter to declaration like updatetbtest(Form_DMM FormDMM). And delete declaration and new in the function body.

messagebox always pop up when clicking combo box

Good day, anyone can help me with this problem... I have a combo box and a textbox. the textbox(txtFruitNo) will check the length of text under Leave event. It is ok. But if I click on the combo box while txtFruitNo is not yet completed. It needs me to complete first the length of txtFruitNo then only I can click the combo box.
I do not want to show the messagebox if I click on the combo box even if the length of the txtFruitNo is not yet completed.
Thanks
private void cmbFruitSelection_SelectedIndexChanged(object sender, EventArgs e)
{
DateTime thetime = DateTime.Now;
String varApple = "App-Red";
String varBanana = "Ban-Yellow";
if (cmbFruitSelection.SelectedItem.ToString() == "Apple")
{
txtFruitNo.Text = varApple.ToString() + thetime.ToString("yyyy");
txtFruitNo.SelectionStart = txtFruitNo.Text.Length;
txtFruitNo.MaxLength = 18;
}
else if (cmbFruitSelection.SelectedItem.ToString() == "Banana")
{
txtFruitNo.Text = varBanana.ToString() + thetime.ToString("yyyy");
txtFruitNo.SelectionStart = txtFruitNo.Text.Length;
txtFruitNo.MaxLength = 17;
}
}
private void txtFruitNo_Leave(object sender, EventArgs e)
{
if (txtFruitNo.TextLength != txtFruitNo.MaxLength)
{
MessageBox.Show("Your fruit number is too short. Please check.");
txtFruitNo.Focus();
}
else
{
// Do something here
}
}
At what point is it important for continuation of the program that the "Fruit Number" is within parameters. If it is not at the time of leaving focus try moving it to a different control for example the "OK" button could run the parameter check and if valid continue if not flag mesage box and return to the textbox
Since your requirement is to only to do the validation and prompt the message box once the user has selected a value from the combo, please do the following;
Introduce a form variable
private bool isComboClicked = false;
Add the below line to cmbFruitSelection_SelectedIndexChanged
isComboClicked = true;
Adding the above line at the beginning of the above event would prompt the length validation message on selection of value from the combo. If you want to prompt message for specific value on the combo move it within the if statements if (comboBox1.SelectedItem.ToString() == "Apple") etc.
Now in txtFruitNo_Leave event enclose the code within the below if condition.
if (isComboClicked)
{
// Your Code
if (txtFruitNo.TextLength != txtFruitNo.MaxLength)
{
MessageBox.Show("Your fruit number is too short. Please check.");
txtFruitNo.Focus();
}
else
{
// Do something here
}
}
As I understand:
You have "validation" on TextBox in Leave eventhandler, which show error message if validation fails.
But if TextBox.Leave event was raised by selecting ComboBox control, then validation must be suppressed.
Create Panel and put there only txtFruitNo and cmbFruitSelection controls.
// Validation function
private bool IsTextBoxValid()
{
return this.txtFruitNo.Length == this.txtFruitNo.maxlength;
}
Then create and hook up Validating eventhandler for Panel where you will validate txtFruitNo
private void Panel_Validating(Object sender, CancelEventArgs e)
{
if(this.IsTextBoxValid() == false)
{
e.Cancel = true;
MessageBox.Show("Your fruit number is too short. Please check.") ;
}
}
Validating will be raised only when focus move outside of the panel.
Using Validating event will prevent changing focus to outside controls automatically if e.Cancel = true
In that case combobox cmbFruitSelection can be focused and user can complete txtFruitNo text by selecting valid value from ComboBox.
I think using of ErrorProvider control will be more friendly for the user, then MessageBox.
Add ErrorProvider control in the Form through designer and add few lines in the code
private void Panel_Validating(Object sender, CancelEventArgs e)
{
if(this.IsTextBoxValid() == false)
{
e.Cancel = true;
this.ErrorProvider1.SetError(txtFruitNo,
"Your fruit number is too short. Please check.");
}
else
{
this.ErrorProvider1.Clear();
}
}
And clear error after valid value was used from ComboBox
private void cmbFruitSelection_SelectedIndexChanged(object sender, EventArgs e)
{
DateTime thetime = DateTime.Now;
String varApple = "App-Red";
String varBanana = "Ban-Yellow";
if (cmbFruitSelection.SelectedItem.ToString() == "Apple")
{
txtFruitNo.Text = varApple.ToString() + thetime.ToString("yyyy");
txtFruitNo.SelectionStart = txtFruitNo.Text.Length;
txtFruitNo.MaxLength = 18;
//Clear error
this.ErrorProvider1.Clear();
}
else if (cmbFruitSelection.SelectedItem.ToString() == "Banana")
{
txtFruitNo.Text = varBanana.ToString() + thetime.ToString("yyyy");
txtFruitNo.SelectionStart = txtFruitNo.Text.Length;
txtFruitNo.MaxLength = 17;
//Clear error
this.ErrorProvider1.Clear();
}
}

Multiple buttons calling a single method

I'm trying to persist CSS user preference to my database according to which of six buttons is selected by the user.
On order to do this, I am trying to assign an integer value to each button click event; whichever is clicked will pass the corresponding integer as a parameter to my data access object to update the database able.
My method reads such:
protected void SetCSS(object sender, EventArgs e)
{
Users setCss = new Users();
if (IsPostBack)
{
if (sender.ToString() == "Blue")
{
setCss.StylePreference = 0;
}
else if (sender.ToString() == "Khaki")
{
setCss.StylePreference = 1;
}
else if (sender.ToString() == "Night")
{
setCss.StylePreference = 2;
}
else if (sender.ToString() == "Pink")
{
setCss.StylePreference = 3;
}
else if (sender.ToString() == "White")
{
setCss.StylePreference = 4;
}
else if (sender.ToString() == "Yellow")
{
setCss.StylePreference = 5;
}
setCss.UserLoginName = Session["eMail"].ToString(); // current user
setCss.SetStylePreference(setCss.UserLoginName, setCss.StylePreference);
}
In each button's click event:
protected void btnBlue_Click(object sender, EventArgs e)
{
SetCSS(btnBlue, null);
}
protected void btnKhaki_Click(object sender, EventArgs e)
{
SetCSS(btnKhaki, null);
}
etc...
I put a watch on the sender object and, when the Pink button is selected, the value assigned to the sender reads
{Text="Pink"}
However, as I step through the if statement in the SetCSS method, when I come to the
else if (sender.ToString() == "Pink")
the condition is not met and, rather than setting the style preference to 3 as it should, the program passes on to the end of the statement, finishing by always assigning a value of 0 to the property.
What am I doing wrong?
Would really appreciate help...
You need to use sender.Id.ToString()
Calling sender.ToString() on an ASP.NET button will return "System.Web.Ui.Button" or something similar.
Paste the code related to how you setup the button and I'll clarify my answer more, as you could need either Id or Text depending on how you're setting the the name on your button.
Realistically, you can refactor this code to be a lot simpler.
You should map the Click event on all of your buttons to SetCSS(). Having a lot of scattered methods to only wrap the call is useless.
Change the if / else block to check for sender.Text
if (sender.Text.ToString() == "Blue")
{
setCss.StylePreference = 0;
}
and do the same for the rest of the statements.

How To Check if button is hovered, and output message

I have 40 buttons in a application that I need custom hovers that will show in a status field. I have made a function for adding a certain message and one to remove, so upon a hover, it calls the function, and same with leaving the button.
I want 40 different messages and one way of doing that is to check which button is being hovered over by the mouse.
if(button1.hovered == true){
string message = "scenario1";
}
elseif(button2.hovered == true){
scenario2...etc
}
Is there a way to check if hovered? and check it in a if statement?
ive decided to add more info so it might be easier to get my point.
add message to listview when mouse hoover.
void messAdd(object sender, EventArgs e)
{
string now = DateTime.Now.ToString("M/d/yyyy") + " - " + DateTime.Now.ToString("HH:mm:ss tt");
string message = "message 1";
found = false;
ListViewItem item = new ListViewItem(message);
foreach (ListViewItem z in listView1.Items)
{
if (z.Text == message)
{ found = true; }
}
if (found == false)
{
item.SubItems.Add(now.ToString());
listView1.Items.Add(item);
listView1.EnsureVisible(item.Index);
}
else
{
DeleteIfNecessary(message);
}
}
delete message from listbox when mouse leave:
void messdel(object sender, EventArgs e)
{
string message = "message 1";
found = false;
ListViewItem item = new ListViewItem(message);
foreach (ListViewItem z in listView1.Items)
{
if (z.Text == message)
{ found = true; }
}
if (found == true)
{
DeleteIfNecessary(message);
}
}
I can make 4 of these functions for each buttons, but since i need 40 different messages, stupid yes, but there is no way to send a message argument through the function, so i need to use the if test and check witch button is hovered and then output the message to that specified button. and im using visual studio and windows forms, sorry for not mentioned.
There is a Control.MouseHover event. You can implement:
private void button_MouseHover(object sender, System.EventArgs e)
{
doSomething(sender);
}
and for all of your buttons, set event handler for MouseHover to button_MouseHover in IDE, or do it in code:
this.button1.MouseHover += new System.EventHandler(this.button_MouseHover);
By checking the sender parameter you can know which button is calling the event handler.
Update
According to your update in the question, I think you can just use messAdd as the event handler for MouseEnter event for all of your buttons, and use messdel as the event handler for MouseLeave. Again, you don't need to create a copy of these two methods for all of your buttons, you just need to assign the same event handler method for all the buttons, and check sender to know who is calling the event handler - then creating different messages.
The sender is your Button object. Just cast it to a Button and access what you want (text, tag, name, etc.) to know which Button is trying to add/remove message on the list view.
Update 2
Button button = sender as Button;
if (button == null) {
// not a button, do nothing
return;
}
string message = String.Empty;
if (sender.Equals(button1)) {
message = "message1";
} else if (sender.Equals(button2)) {
message = "message2";
} ...
I'm going to assume this is WinForms, since you didn't specify otherwise.
You can create an int hoveredId that represents which button is hovered (value -1 means nothing is hovered). When creating the buttons, set the Tag property to the button's id number.
Then register each button to both of these functions:
private void buttons_MouseEnter(object sender, System.EventArgs e)
{
Button btn = ((Button)sender);
hoveredId = (int)btn.Tag;
}
private void buttons_MouseLeave(object sender, System.EventArgs e)
{
Button btn = ((Button)sender);
if ((int)btn.Tag == hoveredId)
hoveredId = -1;
}
When checking which button is hovered, you can use a switch statement:
switch (hoveredId)
{
case 1:
string message = "scenario1";
break;
case 2:
scenario2...etc
break;
}

How to validate array of text boxes

I am using c# winform.
I have 2dimensional array of text boxes I want them to accept only Letters from A-I I've created the method but that works for only one text box.
Here is my code:
textbox[i,j].Validated+=new EventHandler(TextBox_KeyPress);
private void TextBox_KeyPress(object sender, EventArgs e)
{
bool bTest = txtRegExStringIsValid(textbox[1,1].Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", textbox[1,1], 2000);
textbox[1,1].Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
Regex TheRegExpression;
string TheTextToValidate;
string TheRegExTest = #"^[A-I ]+$";
TheTextToValidate = textToValidate;
TheRegExpression = new Regex(TheRegExTest);
if (TheRegExpression.IsMatch(TheTextToValidate))
{
return true;
}
else
{
return false;
}
}
Can anyone please guide what should I do make this code work for all text boxes?
if this works for textbox[1,1] you could register your private void TextBox_KeyPress(object sender, EventArgs e) as eventhandler for all your textboxes and instead of textbox[1,1] you could use ((TextBox)sender)
i want text boxes to accept only letters from a-i actually i am trying to make sudoku
There's a much simpler solution than regular expressions, and you don't even need to handle the Validated event to implement it.
In a situation like this, where there are only certain characters that you want to prevent the user from entering, handling the KeyDown event is a much better solution. The user gets immediate feedback that the letter they tried to enter was not accepted. The alternative (the Validating and Validated events) actually wait until the user tries to leave the textbox to rudely alert them that their input was invalid. Especially for a game, this tends to break concentration and isn't particularly user-friendly.
Doing it this way also makes it irrelevant which individual textbox raised the event. Instead, you will handle it the same way for all of the textboxes—by completely ignoring all invalid input.
Here's what I'd do:
First, attach a handler method to your textbox's KeyDown event. You can do this from the Properties window in the designer, or you can do it through code, as you have in the question:
textbox[i,j].KeyDown += TextBox_KeyDown;
Then, you need to put the logic into your event handler method that determines if the key that the user just pressed is in the allowed range (A through I), or outside of it:
private void TextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Determine if the keystroke was a letter between A and I
if (e.KeyCode < Keys.A || e.KeyCode > Keys.I)
{
// But allow through the backspace key,
// so they can correct their mistakes!
if (e.KeyCode != Keys.Back)
{
// Now we've caught them! An invalid key was pressed.
// Handle it by beeping at the user, and ignoring the key event.
System.Media.SystemSounds.Beep.Play();
e.SuppressKeyPress = true;
}
}
}
If you want to restrict the user to typing in only one letter, you can add code to handle that in the above method, or you can take an even simpler route and let the textbox control handle it for you automatically. To do that, set the MaxLength property of the textbox to true, either in the designer or through code:
textbox[i,j].MaxLength = true;
Check the text of the sender instead of whatever textbox[1,1] is.
Use the sender parameter of the event handler to identify the textbox responsible for the event.
The first thing that will help you is casting the sender of your event to a TextBox like this:
(Also, as Cody Gray said, this is a TextBox_Validated event, not a KeyPress event so I've renamed it appropriately)
private void TextBox_Validated(object sender, EventArgs e)
{
TextBox tb = sender as TextBox()
if (sender == null)
return;
bool bTest = txtRegExStringIsValid(tb.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false) {
tip.Show("Only A-I", tb, 2000);
tb .ext = " ";
}
Next you need to actually get into that code for every textbox. There are two obvious approaches to that, you can either assign the eventhandler to each textbox in the array or you can use a custom textbox which always does this validation and then add that to your array.
Assign eventhandler to textboxes
foreach(var tb in textbox)
{
tb.Validated += new EventHandler(TextBox_KeyPress);
}
Create custom textbox control
Create the custom text box control (Add a user control to the project) and then just use it exactly as you would a normal textbox.
public partial class ValidatingTextBox: TextBox
{
public ValidatingTextBox()
{
InitializeComponent();
}
protected override void OnValidating(CancelEventArgs e)
{
bool bTest = txtRegExStringIsValid(this.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", this, 2000);
this.Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
// Exactly the same validation logic as in the same method on the form
}
}

Categories

Resources