prevent repetitive code in C# - c#

I'm writing a desktop app in win forms using C#.I use the following code to convert my textbox to numeric textboxes :
private void txtPrice_KeyPress(object sender, KeyPressEventArgs e)
{
//if (!char.IsControl(e.KeyChar)
// && !char.IsDigit(e.KeyChar)
// && e.KeyChar != '.')
// {
// e.Handled = true;
// }
if(!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
is it ant design pattern or technique to write above code only once, and dont write it , each time for every textbox in the form?

Subclass the TextBox class, add your numeric checking to it, and use the new text box in place of the usual one.
Example
How to: Create a Numeric Text Box

Create a new component called numeric textbox that inherits TextBoxBase class.
Your code you wrote here won't work because someone can copy and paste text values.
You have to override text_change event for that.

If you want customisation, Robert's answer is the best way to go. Alternatively, in case you're not aware of it, you could use the NumericUpDown control which is built in.

create a method....for example
private void press(object sender, KeyPressEventArgs e)
{
//what ever code here,,,,,,i dont care
}
//i am assuming you are using visual studio.net
//highlight or select your text boxes or text box....
//then go to properties window ,,,,,
//after that click on the lightening icon....or events icon
//then go to your KeyPress event------- and click the drop down button
//after that Add the Method you want to be implemented by the Control.......

Related

Validating textbox content if checkbox has been checked

I'm trying to do a validation wherein if a checkbox has been ticked, the corresponding textbox would no longer be in ReadOnly mode and should not be empty. For example, if I checked CheckBox1, if TextBox1 did not have any input, a MessageBox would pop up to say that "Please fill up the entire form!". Else, it would display "Done!".
This is what I have so far:
if ((CheckBox1.Checked && TextBox1.Text == "")
|| (CheckBox2.Checked && TextBox2.Text == ""))
MessageBox.Show("Please fill up the entire form!");
else if (CheckBox1.Checked && TextBox1.Text != "")
MessageBox.Show("Done!");
else if (CheckBox2.Checked && TextBox2.Text != "")
MessageBox.Show("Done!");
I've made a couple of checkboxes/textboxes that would require this validation and I find that it gets kind of lengthy so I was wondering if there's a simpler/better approach.
(not sure if relevant) Note: I got the toggling the ReadOnly mode when the CheckChanged event is triggered part down
There could be some enhancements for your code, for example:
You can use this criteria !textBox.ReadOnly && string.IsNullOrEmpty(textBox.Text) rather than what you have.
You can avoid using those else if parts and just return from the method if there is a validation error and just put the code after the validation block.
A better solution - Using Validating Event
But I'd rather to change the whole style of validation and use Validating event of those TextBox controls. To do so, you need to follow these instructions:
1) Set AutoValidate property of form to EnableAllowFocusChange in design mode or using code in Load event of form.
2) Handle Validating event of all TextBox controls using single a method and set e.Cancel = true; when there is validation error:
private void textBox_Validating(object sender, CancelEventArgs e)
{
var textBox = (TextBox)sender;
if (!textBox.ReadOnly && string.IsNullOrEmpty(textBox.Text))
e.Cancel = true;
}
3) In the save button of your form, using ValidateChildren method of the form, check if there is any validation error, show a message, otherwise do what the button is supposed to do:
private void button1_Click(object sender, EventArgs e)
{
if (!this.ValidateChildren())
MessageBox.Show("Please correct validation errors.")
else
MessageBox.Show("Done!")
}
Note
To read more about validation options in Windows Forms, take a look at this post:
Validating user input / Give .NET controls status OK or NOK
Also if you want to enhance the user experience by showing a validation error/icon near the control using an ErrorProvider, take a look at this post:
Validation using Validating event and ErrorProvider - Show Error Summary

DataGridView MaskedTextBoxColumn

I have a DataGridView, and I would like to have something similar to a MaskedTextBox inside my DataGridView. It doesn't have to be an exact MaskedTextBox, but at least somewhat acting like one.
Here is what my DataGridView looks like.
All I want is that the people who modify the DataGridView's right column (Durée - 'Duration'), follow the Mask pattern 00:00:00 for time.
Another solution would be to place a DateTimePicker. But similar to the solution using a MaskedTextBox, it does supposedly not exist as DataGridView columns.
I have tried using the Column's Builder to add a Behavior→Format, but I don't think this is quite the same. I need something to prevent the user from adding random stuff.
You have (at least) two options:
You can use a regular MaskedTextBox overlaid over the TextBox the DGV creates for editing
You can code the regular edit control, i.e. the TextBox the DGV shows when entering edit mode.
Here are examples for both:
First we create class level variables for the controls:
TextBox editBox = new TextBox();
MaskedTextBox editMBox = new MaskedTextBox();
To get a reference to the editing textbox we code the EditingControlShowing event:
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
editBox = e.Control as TextBox;
}
To control user input we hook up the KeyPress event:
public Form1()
{
InitializeComponent();
..
editBox.KeyPress += editBox_KeyPress;
..
}
Here we can do all sorts of check and prevent bad characters from entering. All the regular properties are there..:
void editBox_KeyPress(object sender, KeyPressEventArgs e)
{
string sNew = editBox.Text.Substring(0, editBox.SelectionStart)
+ e.KeyChar + editBox.Text.Substring(editBox.SelectionStart);
Console.WriteLine(sNew);
e.Handled = !validateMethod(sNew);
}
This would call a function you can write..
But if you are happy with what a MaskedTextBox you can simply use one:
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewCell cell = dataGridView1.CurrentCell;
editMBox.Parent = dataGridView1;
editMBox.Location = dataGridView1.GetCellDisplayRectangle(cell.ColumnIndex,
cell.RowIndex, false).Location;
editMBox.Size = editBox.Size;
editMBox.Show();
editMBox.Mask = yourMask;
editMBox.BringToFront();
}
We need to hook up the KeyPress event for the MaskedTextBox to end to editing. Here is just a simple way to accept the value when Enter is pressed.
You will want to handle Esc here and also at least the CurrentCellChanged event for more complete control..
void editMBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
editBox.Text = editMBox.Text;
editMBox.Hide();
}
}
I found this neat little program MaskedTextBoxColumn in DataGridViews. I had found that a little earlier, but was reluctant to download it since we had to register and stuff. Actually worked out pretty well. The mask properties is a little too simple, as it is lacking some nice features, but the general MaskedTextBox idea is there.

Suppress the display of the input into the TextBox

I have a winforms program containing a RichTextBox.
The user inputs the text into the RichTextBox.
I wish to receive the input through keyboard events and not through textBox1.Text property, validate the string and only display it in the RichTextBox later.
How can I prevent the RichTextBox from displaying the input text by the user, even though the user inputs the text into the RichTextBox?
The RichTextBox is selected and has focus.
I am sorry. I just wanted to simplify the issue and therefore I neglected to mention that it is not a TextBox but a RichTextBox. It turns out that it matters, as the proposed solution is based on the PassowrdChar property, which is not natively supported by RichTextBox. I do not wish to create an inherited class for a property which is not even being used as such, only to suppress displaying the user input at input time.
You can actually use the KeyDown event. By doing that, you have an ability to validate the user input.
Tutorial
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
//
// Detect the KeyEventArg's key enumerated constant.
//
if (e.KeyCode == Keys.Enter)
{
MessageBox.Show("You pressed enter! Good job!");
}
else if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("You pressed escape! What's wrong?");
}
}
With that said, you have to store user input in string variable, validate it through the event and only then set variable value in textbox.
You can use this:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char c = e.KeyChar;
// ..
// handle the character as needed
// ..
e.Handled = true; // suppress the RTB from receiving it
}
Note that you may or may not want to treat mouse events like right mouseclicks to control inserting via the mouse..

How to set TextBox to only accept numbers?

I have already checked other questions here but the answers are not related to my issue. the following code allows textbox1 to only accept numbers if the physical keyboard (laptop) is pressed:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char ch = e.KeyChar;
if ( !char.IsDigit(ch))
{
e.Handled = true;
}
}
but this is not what I wanted (I dont use physical laptop keyboard).
As shown in screenshot, I have windows form with buttons and a textbox. I designed this keyboard and it works well but I want textbox1 to only accept numbers and the ".".
There are only two lines of code inside each button (and only code in the project) which is:
private void buttonName_Click(object sender, EventArgs e)
{
// each button only has this code.
textBox1.Focus();
SendKeys.Send(buttonName.Text);
}
I know how to set txtbox to accept numbers if the physical (laptop ) keys are pressed but here in this case I have control buttons in windwos form and I want to set textBox1 to only accept numbers and the ".". Please help in how to achieve this. Thank you
Declare a string variable at form level, use it to store the last valid text and to restore it when an invalid text is entered on the TextChanged event of your textbox.
string previousText;
public Form1()
{
InitializeComponent();
previousText = String.Empty;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int dummy, changeLenght, position;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !int.TryParse(textBox1.Text, out dummy))
{
position = textBox1.SelectionStart;
changeLenght = textBox1.TextLength - previousText.Length;
textBox1.Text = previousText;
textBox1.SelectionStart = position - changeLenght;
}
else
{
previousText = textBox1.Text;
}
}
position and changeLenght are used to keep the cursor where it was before restoring the text.
In case you want to accept numbers with decimals or something bigger than 2147483647, just change dummy to double and use double.TryParse instead of int.TryParse.
private void textBox1_TextChanged(object sender, EventArgs e)
{
int changeLenght, position;
double dummy;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !double.TryParse(textBox1.Text, out dummy))
{
...
}
}
Suppose button1 is your button control, you could do this:
private void allButtons_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
char c = btn.Text[0]; //assuming all buttons have exactly 1 character
if(Char.IsDigit(c) || c == '.')
{
//process
textBox1.Focus();
SendKeys.Send(btn.Text);
}
//otherwise don't
}
I'm assuming you put this in a common handler, to which you already wired all your buttons (i.e. allButtons_Click).
Problem with this approach, it allows you to type values like 0.0.1, which are most likely invalid in your context. Another way to handle this is to process TextChanged event, store previous value, and if new value is invalid, restore the old one. Unfortunately, TextBox class does not have TextChanging event, which could be a cleaner option.
The benefit of you determining the invalid value is modularity. For example, if you later decide your user can enter any value, but only numbers can pass validation, you could move your check from TextChanged to Validate button click or similar.
Why users may want that - suppose one of the options for input is copy/paste - they want to paste invalid data and edit it to become valid, for example abc123.5. If you limit them at the entry, this value will not be there at all, so they now need to manually paste into Notepad, cut out in the invalid characters, and paste again, which goes against productivity.
Generally, before implementing any user interface limitation, read "I won't allow my user to...", think well, whether it's justified enough. More often than not, you don't need to limit the user, even for the good purpose of keeping your DB valid etc. If possible, never put a concrete wall in front of them, you just need to guide them correctly through your workflow. You want users on your side, not against you.

How to detect if an event is sent by an argument

I don't know if it is called an argument (i.e. textbox1.text = "Hello";).
I have a control and there is a text box in it. It has a dropdown box that opens when the text is changed. But when I update the text in the text box that box drops down.
I need a way to make it so it only drops down if someone manually does it.
TBAddressBar.ABText.Text = getCurrentBrowser().Source.ToString();
and
public void ABText_TextChanged(object sender, TextChangedEventArgs e)
{
if (sender == 1*)
{
ABDropDown.Visibility = Visibility.Visible;
}
else
{
ABDropDown.Visibility = Visibility.Collapsed;
}
}
If someone manually does it, presumably they are using keypresses to do so. In that case, use KeyDown or KeyUp events to show the dropdown instead.
What I have done in the past is use a boolean variable that I set when I update my textboxes programically to bypass the TextChangedEvent.
i.e.
bool loading;
....
loading =true;
TBAddressBar.ABText.Text = getCurrentBrowser().Source.ToString();
loading = false;
public void ABText_TextChanged(object sender, TextChangedEventArgs e)
{
if(loading) return;
....
}
Simple, just remove the code from your TextChanged Event.
Anyway you got the basic idea.. Now do your dropdown logic in KeyPress event, since it accepts only characters and not the modifiers. So it behaves closer to your requirement. Not that you cant handle the same using KeyDown and KeyUp, you can, but more code..

Categories