Textbox KeyPress Event? - c#

i have textbox only allow decimals and '+'
it allow only 1 Decimal "12.332" i need to allow 1 decimal before '+' and 1 decimal after '+' Example i have 12.43+12.23 i can't type the 12(.) because i allow only 1 decimal i am using Split method to get 2 parts before and after
and it is my code
// checks to make sure only 1 decimal is allowed
if (e.KeyChar == 46)
{
if ((sender as TextBox).Text.IndexOf(e.KeyChar) != -1)
e.Handled = true;
}
And this is My method
if(textBox1.Text.Contains('+')==true )
{
string Value = textBox1.Text;
string[] tmp = Value.Split('+');
string FirstValu = tmp[1];
string SecValu = tmp[0];
}
how to use method with event to allow another decimal place after '+'

I would say use two text boxes like someone said in the comments but if you want to be stubborn here is a function to run inside an event that is called when the text changes in the text box.
void textbox_textChanged(object sender, EventArgs e)
{
string text = textBox.Text;
int pointCounter = 0;
int addCounter =0
string temp = "";
string numbers = "0123456789";
for(int i =0;i<text.Length;i++)
{
bool found = false;
for(int j = 0;j<numbers.Length;j++)
{
if(text[i]==numbers[j])
{
temp+=text[i];
found = true;
break;
}
}
if(!found)
{
if('.' == text[i])
{
if(pointCounter<1)
{
pointCounter++;
temp+=text[i];
}
}else
if('+' == text[i])
{
if(addCounter<1)
{
pointCounter=0;
addCounter++;
temp+=text[i];
}
}
}
}
textBox.text = temp;
}

I would recommend using a Regex to validate your textbox. I would also suggest that using the textbox Validating event would be better than using the Leave event. Here is an example of using a regex in the Validating event:
private void textBox1_Validating(object sender, CancelEventArgs e)
{
TextBox tbox = (TextBox)sender;
string testPattern = #"^[+-]?[0-9]*\.?[0-9]+ *[+-]? *[0-9]*\.?[0-9]+$";
Regex regex = new Regex(testPattern);
bool isTextOk = regex.Match(tbox.Text).Success;
if (!isTextOk)
{
MessageBox.Show("Error, please check your input.");
e.Cancel = true;
}
}
You will find the Regex class in the System.Text.RegularExpressions namespace. Also make sure your textbox has the CausesValidation property set to true.
As an alternative you might also want to look at using the MaskedTextBox Class.

Related

C# Search for first number in integer/string

I have a textbox where people have to enter a number but I don't want to them to type the number 0 in first, how do I do this?
Example: If they type, 10 it's ok but if they type 010 it's not ok and I want a window to appear and tell them to try again.
Thanks!
Add TextChanged handler to your textbox (in your form find event for TextBox and type this name: TextBox_TextChanged):
void TextBox_TextChanged(object sender, EventArgs e)
{
var textBox = sender as TextBox;
if (textBox != null)
{
textBox.Text = textBox.Text.Trim();
if (textBox.Text.Length > 0 && textBox.Text[0] == '0')
{
textBox.Text = textBox.Text.TrimStart('0');
MessageBox.Show("Incorrect value");
}
}
}
Or in code:
TextBox textBox = new TextBox();
textBox.TextChanged += TextBox_TextChanged;
Use the TextChanged event. (Double click on the event in the properties of the textbox in the designer) In this example trim any leading spaces before comparison and remove the character if it is a 0
private void textBox1_TextChanged(object sender, EventArgs e)
{
string input = textBox1.Text.TrimStart(' ');
if (input.Length == 1)
{
textBox1.Text = input == "0" ? "" : input;
}
}
EDIT
As pointed out by m.rogalski and Roma the version above allows for entering the 0 after the input of a valid character. This version bellow will correct this mistake:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.Text = textBox1.Text.TrimStart('0');
}
This should work:
private void MyTextBox_TextChanged(object sender, EventArgs e)
{
var textBox = sender as TextBox;
if (textBox.Text.StartsWith("0"))
//alert user
MessageBox.Show("Invalid starting character");
}
Of course you need to bind TextChanged event in designer or in code like this:
MyTextBox.TextChanged += MyTextBox_TextChanged;
Starting from the beginnign :
If they type, 10 it's ok but if they type 010 it's not ok
If it's okay for user to type integer ranging from 0 to infinity then you can use this :
if(textBox.Text.Length > 1 && textBox.Text[0] == '0')
This assumes that user can type '0' as a first sign only if it is only sign. If that's not what you wanted then change it to this :
if(textBox.Text.Length > 0 && textBox.Text[0] == '0')
Going further :
I want a window to appear and tell them to try again
You can just show MessageBox and clear text inside textBox :
textBox.Text = string.Empty;
MessageBox.Show("Value entered is incorrect. Please try again");
Then combining these you'll have something like :
if(textBox.Text.Length > 1/* or 0 depending on what you need */ && textBox.Text[0] == '0')
{
textBox.Text = string.Empty;
MessageBox.Show("Value entered is incorrect. Please try again");
}
put this code to after Initialize method
textBox1.TextChanged = (s, o) =>
{
if (textBox1.Text.StartsWith("0"))
{
textBox1.Text = textBox1.Text.Remove(0, 1);
MessageBox.Show("Cant start with '0'");
}
};
Perhaps you could have a ViewModel representing some textboxes, one of which is your "Number" textbox. Then you can use an attribute on your Number property to make sure it is validated.
public class MyViewModel
{
...
[Required]
[NumberValidation]
string NumberTextBox {get;set;}
where NumberValidation is another public class implementing a ValidationAttribute
[AttributeUsage(AttributeTargets.Property]
public class NumberValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value.StartsWith("0"))
{
return new ValidationResult(ErrorMessage, "Please enter another number!");
}
return ValidationResult.Success;
}
}

MaskedTextBox Currency Input Mask Limits

Im trying to make a Custom Input Mask for currency in Visual Studio 2013
But, this type of mask has a limit: 9999,00.
I can't write numbers like 99999999,00.
I want a mask that works with any amount of numbers
Is it possible?
The standard way of applying the mask via Regular Expresions is detailed in Microsoft documentation: https://msdn.microsoft.com/en-us/library/ms234064.aspx Pertinent to your case it could be something like: $\d{9}.00 Hope this may help.
This worked for me. Instead of creating a custom mask, create a custom maskedTextbox.
Even with the correct mask, the delivered maskedTextBox is difficult for users to enter data. The currencyTextbox automatically formats/shifts the entered values.
https://blogs.msdn.microsoft.com/irenak/2006/03/21/sysk-87-a-better-maskedtextbox-for-currency-fields/
Once you add that class to your project, you'll see the currencyTextBox appear in your toolbox. Then just set a mask for it depending on how large a dollar value you want to store. According to the author, you use all 0s, I personally used "$000,000.00"
//Crie um textbox com o name txt_valor e atribua os eventos KeyPress,KeyUp e
// Leave e uma string valor;
string valor;
private void txt_valor_KeyPress(object sender, KeyPressEventArgs e)
{
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != Convert.ToChar(Keys.Back))
{
if (e.KeyChar == ',')
{
e.Handled = (txt_valor.Text.Contains(","));
}
else
e.Handled = true;
}
}
private void txt_valor_Leave(object sender, EventArgs e)
{
valor = txt_valor.Text.Replace("R$", "");
txt_valor.Text = string.Format("{0:C}", Convert.ToDouble(valor));
}
private void txt_valor_KeyUp(object sender, KeyEventArgs e)
{
valor = txt_valor.Text.Replace("R$","").Replace(",","").Replace(" ","").Replace("00,","");
if(valor.Length == 0)
{
txt_valor.Text = "0,00"+valor;
}
if(valor.Length == 1)
{
txt_valor.Text = "0,0"+valor;
}
if(valor.Length == 2)
{
txt_valor.Text = "0,"+valor;
}
else if(valor.Length >= 3)
{
if(txt_valor.Text.StartsWith("0,"))
{
txt_valor.Text = valor.Insert(valor.Length - 2,",").Replace("0,","");
}
else if(txt_valor.Text.Contains("00,"))
{
txt_valor.Text = valor.Insert(valor.Length - 2,",").Replace("00,","");
}
else
{
txt_valor.Text = valor.Insert(valor.Length - 2,",");
}
}
valor = txt_valor.Text;
txt_valor.Text = string.Format("{0:C}", Convert.ToDouble(valor));
txt_valor.Select(txt_valor.Text.Length,0);
}

DataGridView attempting to save bound data with formatted value?

I am attempting to format a time value from a mssql database. The value is stored in the database as an int with hhmm as the format(for example: 1900 or 2130) I am unable to edit the database format as it is used by other software as well.
It is automatically bound to the DataGridView, and this has worked perfectly. However the specification I am working to says that it MUST show as a standard time format. So I have used the CellFormatting Event to show the times like 19:00 and 21:30.
It shows the value fine, however when I go to edit this value using the DataGridView it doesn't change it back to the unformatted value so I get the formatted value in the edit box. If I don't remove the colon I get an exception about saying Input is Invalid.
It was my understanding that the formatted value and the true value are not the same and this wouldn't cause an issue.
My code for formatting his below:
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == -1)
return;
string CellName = dataGridView1.Columns[e.ColumnIndex].Name;
if (timeFormattedCells.Contains(CellName))
{
if (e.Value != null)
{
try
{
string currentFormat = e.Value.ToString();
if (currentFormat.Length == 3)
{
currentFormat = "0" + currentFormat;
}
DateTime dateTime = DateTime.ParseExact(currentFormat, "HHmm",CultureInfo.InvariantCulture);
currentFormat = dateTime.ToShortTimeString();
e.Value = currentFormat;
e.FormattingApplied = true;
}
catch (FormatException)
{
e.FormattingApplied = false;
}
}
}
}
I also need to ensure that the user cannot put an invalid time like 2405 or 1299.
Does anyone have a suggestion that might help me out?
Thanks
As long as your CellFormatting event is formatting the way you want, I would probably check the validity of the time first and then convert it to int...I would try something like this:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
bool valid;
DataGridView dgv = (DataGridView)sender;
DataGridViewCell cell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
// Regex pattern acceptable for a time format
Regex timeRegex = new Regex("^([0-1]?[0-9]|[2][0-3]):([0-5][0-9])$");
if (cell.Value == null || cell.Value.ToString() == string.Empty)
{
cell.Style.BackColor = Color.White;
cell.ToolTipText = string.Empty;
cell.Tag = "empty";
valid = false;
}
// If the regex does not match then the format is invalid
else if (!timeRegex.IsMatch(cell.Value.ToString()))
{
cell.Style.BackColor = Color.Beige;
cell.ToolTipText = "Invalid format.";
cell.Tag = "invalid";
valid = false;
}
else
{
cell.Style.BackColor = Color.White;
cell.ToolTipText = string.Empty;
cell.Tag = "valid";
valid = true;
}
if(valid)
{
string timeToConvert = cell.Value.ToString();
string timeConvertReady = timeToConvert.Replace(":", "");
int timeAsInt = Convert.ToInt32(timeConvertReady);
updateTimeInDatabase(timeAsInt);
}
}
updateTimeInDatabase(timeAsInt) would be a method that sends the update command. This could also be a TableAdpater method or whatever you are using. If it was a TableAdapter the syntax would look something like testTableAdapter.Update(timeAsInt);

How to make winforms textbox autocomplete correct capitalisation?

Using a winforms textbox with autocomplete set to SuggestAppend I can type out part of a string and the rest will be suggested to me fine.
If a user types "smi" looking for "Smith, John" and then autocompletes the rest of the string by tabbing then the textbox contains "smith, John". But, if the user clicks on the name then the capitalisation is correct.
Is there a way I can get the autocomplete to re-capitalise the user inputted part of the string when the suggestion is accepted by tabbing?
Pressing tab leads to:
Clicking name leads to (this is what I want):
To handle this situation I handled the textbox Leave event. The idea is to split the text by comma, uppercase the first letter of the resulting strings, then join the strings back together.
private void textBox1_Leave(object sender, EventArgs e)
{
string[] strings = this.textBox1.Text.Split(new char[] { ',' });
for (int i = 0; i < strings.Length; i++)
{
strings[i] = string.Format("{0}{1}", char.ToUpper(strings[i][0]), strings[i].Substring(1));
}
this.textBox1.Text = string.Join(",", strings);
}
Here's the function I came up with the end, it replaces the textbox's content with a line from the AutoCompleteCustomSource of the textbox (sorted alphabetically).
So, this will still work for any case (e.g if user entered "aLLeN" it would still correct to "Allen,Charlie (ID:104)"
private void fixContent()
{
String text = txtAutoComplete.Text;
List<String> matchedResults = new List<String>();
//Iterate through textbox autocompletecustomsource
foreach (String ACLine in txtAutoComplete.AutoCompleteCustomSource)
{
//Check ACLine length is longer than text length or substring will raise exception
if (ACLine.Length >= text.Length)
{
//If the part of the ACLine with the same length as text is the same as text, it's a possible match
if (ACLine.Substring(0, text.Length).ToLower() == text.ToLower())
matchedResults.Add(ACLine);
}
}
//Sort results and set text to first result
matchedResults.Sort();
txtAutoComplete.Text = matchedResults[0]
}
Thanks to OhBeWise I attached this to the textbox leave event:
private void txtAutoComplete_Leave(object sender, EventArgs e)
{
fixContent();
}
But also I needed to cover situations when the autocomplete has been accepted which occur when enter, tab, left and right are pressed. Attaching this to the keydown event doesn't work because I think the autocomplete captures the event beforehand, so I attached to the previewkeydown event:
private void txtAutoComplete_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
Keys key = (Keys)e.KeyCode;
if (key == Keys.Enter || key == Keys.Tab || key == Keys.Left || key == Keys.Right)
{
fixContent();
}
}
simple ;
private void textbox_TextChanged(object sender, EventArgs e)
{
AutoCompleteStringCollection a = new AutoCompleteStringCollection();
a = textbox.AutoCompleteCustomSource;
for (int i = 0; i < a.Count; i++)
{
if (a[i].ToLower() == textbox.Text.ToLower())
{
textbox.Text= a[i].ToString();
break;
}
}
}

Verify a Color Has Been Inputted in a DataGridView

I have a datagridview where one of the columns is a color column. I want to ensure the user enters a valid color, otherwise leave the cell blank.
When the cell is starting from blank, the following code gives me a null reference exception. Fyi, I am doing this in the CellLeave event.
Answer I had to move the code to the CellFormatting event. For some reason, the value at the cell does not get updated until a certain unknown point. For my check, I need to do it before something I was doing in the CellFormatting event. Moving the code there fixed my problem.
private void dataGridView1_CellFormatting(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex.Equals(2))
{
Regex test = new Regex("[0-255],[0-255],[0-255]");
Match m = test.Match(this.dataGridView1.CurrentCell.Value.ToString());
if(!m.Success)
{
this.dataGridView1.CurrentCell.Value = "";
}
}
}
To validate a string you could use this method:
private static bool IsValidColorString(string input)
{
if (String.IsNullOrEmpty(input))
return false;
string[] parts = input.Split(',');
if (parts.Length != 3)
return false;
foreach (string part in parts)
{
int val;
if (!int.TryParse(part, out val) || val < 0 || val > 255)
return false;
}
return true;
}
The best place to use it I believe is the DataGridView.CellParsing event handler:
private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
if (e.Value == null || e.ColumnIndex != 2) // Skip empty cells and columns except #2
return;
string input = e.Value.ToString();
if (!IsValidColorString(input))
e.Value = String.Empty; // An updated cells's value is set back to the `e.Value`
}
An updated cells's value is set back to the e.Value instead of the DataGridView.CurrentCell.Value.
Try this for your match:
Match m = test.Match((this.dataGridView1.CurrentCell.Value ?? "").ToString());
This will replace a null value with an empty string when matching.
Do you perhaps need to check to see if there is a value within the cell before you try and match a Regex?
if (e.ColumnIndex.Equals(2))
{
if(this.dataGridView1.CurrentCell.Value != null)
{
...
CurrentCell.Value.ToString()
Causing the error..
CurrentCell.value=null
null value can't cast using the tostring() method,that's why you are getting ther null reference exception.
try this..
string val="";
if(dataGridView1.CurrentCell.Value==null)
{
val=""
}
els
else
{
val=convert.tostring(dataGridView1.CurrentCell.value);
}
Match m = test.Match(val);
if(!m.Success)
{
this.dataGridView1.CurrentCell.Value = "";
}

Categories