How to handle a group of textbox/label in an array - c#

I have a serie of textboxes and labels form textbox 1-9 and label 1 to 9. With a click on a any label I clear the correspondant textbox.
I created a methode but it's like a baby toy comparison to my procedures in TP or VB. There must be a shortest well structered way. Any idea wiil be very much appreciated?
What I did :)))
private void label1_Click(object sender, EventArgs e)
{
textBox1.Text = "" ;
}
private void label2_Click(object sender, EventArgs e)
{
textBox2.Text = "" ;
}
private void label3_Click(object sender, EventArgs e)
{
textBox3.Text = "" ;
}
private void label4_Click(object sender, EventArgs e)
{
textBox4.Text = "" ;
}
private void label5_Click(object sender, EventArgs e)
{
textBox5.Text = "" ;
}
private void label6_Click(object sender, EventArgs e)
{
textBox6.Text = "" ;
}
private void label7_Click(object sender, EventArgs e)
{
textBox7.Text = "" ;
}
private void label8_Click(object sender, EventArgs e)
{
textBox8.Text = "" ;
}
private void label9_Click(object sender, EventArgs e)
{
textBox9.Text = "" ;
}

You can utilize Tag property to mark controls. Then you can iterate through them (preferably starting from most parent control - form and with the use of recursion! or, if you are sure, from the container, which holds the group of controls).
// assign tag "1" to "9" to labels and texboxes
// subscribe all labels to same event label_Click
private void label_Click(object sender, EventArgs e)
{
string id = (sender as Control).Tag.ToString();
// iterate or recurse
FindTextboxWithId(id).Clear();
}
// it shouldn't be hard to write FindTextboxWithId
Other possibility is to create private arrays of controls, in the form constructor, just to ease referencing them.
public TextBox[] _textBox;
public Form1()
{
InitializeComponent();
_textBox = new TextBox[] {textBox1, texBox2, ..., textBox9};
}
// assign tag "0" to "8" to labels and texboxes
// subscribe all labels to same event label_Click
private void label_Click(object sender, EventArgs e)
{
int index = int.Parse((sender as Label).Tag);
_textBox[index].Clear();
}
Third possibility is to utilize containers, to example, TableLayoutPanel. You can create 2 column container where first column is Label's and second is TextBox'es. Then just fill 9 rows and have fun in OnClick (to find sender position, to find texbox position, to find textbox and to finally clear it).

Perhaps one handler for all and using Controls.Find:
private void label_Click(object sender, EventArgs e)
{
var label = (Label)sender;
string lastDigits = new string(label.Name.SkipWhile(c => !Char.IsDigit(c)).ToArray());
var textBox = Controls.Find("textBox" + lastDigits, true).FirstOrDefault() as TextBox;
if(textBox != null)
textBox.Text = "" ;
}
Although relying on those meaningless variable names is not best practise.

To make your code less redundant, you can loop over the controls in your application:
Control Class, so when clicking on a label you will have to search for the textBox's Tag
that you will set for each textBox.
foreach (Control C in this.Controls)
{
//Code Here...
}

Quick solution:
Rename your labels like: label_1, label_2, ... label_22, then you can use the following common event-handler for all clicks.
An improvement on this would be to just pass labelNr to a separate number, which would then use that to find the textbox by name, instead of using a swith to check all of them. I don't have time to try that now, but I'm sure you can figure it out somehow.. ;)
private void label1_Click(object sender, EventArgs e)
{
var labelNr = ((Label) sender).Name.Split('_').Last();
switch (labelNr)
{
case "1":
textBox_1.Clear();
break;
case "22":
textBox_22.Clear();
break;
}
}
Update: Seems Tim Schmelter had the answer here. To steal a small detail from him: Use Controls.Find("textBox" + labelNr, true) as he shows above instead of the switch here, and you should be set.

And a javascript solution:
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
<asp:Label ID="lbl1" runat="server" AssociatedControlID="txt1" onclick="clearTextBox(this)">Clear</asp:Label>
function clearTextBox(sender){
var assocControlId = sender.htmlFor;
var el = document.getElementById(assocControlId);
if (el)
el.value = '';
}

I would suggest you create a UserControl
Arrange a Lable and a TextBox
handle the label_click event
and uses that UserControl on your form instead.
something like this:
public class LableAndTextBox : UserControl
{
public LableAndTextBox()
{
InitializeComponents();
}
public void label_Click(object sender, EventArgs e)
{
textBox.Text = string.Empty;
}
}
Edit - make sure you create the userControl, in a seperate assembly - for compile reasons..

With two solutions of #sinatr I've created one other method because both are given an error message.
private void label_Click (object sender , EventArgs e)
{
string id = (sender as Control).Tag.ToString();
int newidx = Convert.ToInt32(id);
_textBox[newidx].Clear();
}
THIS WORKS!
Sure! I've added juste here this
namespace WindowsFormsApplication1
{
public partial class
DefBiscuit : Form
{
public TextBox[] _textBox;
And
In form_load this
_textBox = new TextBox[] { textBox1, textBox2, textBox3, textBox4, textBox5, textBox6, textBox7, textBox8, textBox9 };

If you don't like to write code much, i have a program can write it fast.
For example, if you input "lable1.Text = textbox1.Text;" and "15" the program will output into a textbox:
lable1.Text = textbox1.Text;
lable2.Text = textbox2.Text;
lable3.Text = textbox3.Text;
lable4.Text = textbox4.Text;
lable5.Text = textbox5.Text;
lable6.Text = textbox6.Text;
...
lable15.Text = textbox15.Text;
Go here to know more and download: Download Counter Replacer

Related

How to standardize many button events C#

Could you tell me how to put together the many button event.
Writing all the many button event is bad Maintainability.
So I want to turn many button event into one method.
Like this...
Before
private void button1_Click(object sender, EventArgs e)
{
//button1 event
}
private void button2_Click(object sender, EventArgs e)
{
//button2event
}
private void buttonN_Click(object sender, EventArgs e)
{
//buttonNevent
}
After
private void buttonClickEvent(object sender, EventArgs e)
{
Button btn = (Button)sender;
int index = int.Parse(btn.Name.Replace("button", ""));
if(index==1)
{
//button1 event
}
if(index==2)
{
//button2 event
}
}
In ASP.NET Web Forms I've solved this situation like this.
Define a general hidden button (this will be the trigger for all). You should define it "hidden" using the styles.
<asp:Button ID="btnPrintPdf" runat="server" Style="display: none" OnClick="btnPrint_Click" />
For the all other buttons "redirect" the click on the client side to the general one like this:
btnPrintPlan.OnClientClick = ClientScript.GetPostBackClientHyperlink(btnPrintPdf, itemData.ClientIw.ID.ToString() + "|" + ((int)PrintDocs.NextStepsPlan).ToString()) + ";return false;";
btnPrintNetWorth.OnClientClick = ClientScript.GetPostBackClientHyperlink(btnPrintPdf, itemData.ClientIw.ID.ToString() + "|" + ((int)PrintDocs.NetWorth).ToString()) + ";return false;";
As you can see, I use a Enum to define what I want to print by clicking different buttons.
The last part is to define the "general" button logic:
protected void btnPrint_Click(object sender, EventArgs e)
{
string sVal = Request.Params["__EVENTARGUMENT"];
if (string.IsNullOrEmpty(sVal))
return;
string[] tks = sVal.Split('|');
if (tks.Length != 2)
return;
string sOrderId = tks[0];
string sPrintType = tks[1];
int orderId = 0;
int iPrintType = 0;
if (!int.TryParse(sOrderId, out orderId) || !int.TryParse(sPrintType, out iPrintType))
return;
string sPdf = null;
if (iPrintType == (int)PrintDocs.NextStepsPlan)
{
....
}//endif
if (iPrintType == (int)PrintDocs.NetWorth)
{
....
}//endif
You could try something like this. Dictionary would be better than if's if you have hundreds of buttons.
private Dictionary<string, Action<object, EventArgs>> buttonEventMap = new Dictionary<string, Action<object, EventArgs>>();
private void setup()
{
buttonEventMap["button1"] = (object sender, EventArgs e)=>{Console.WriteLine("Button 1 Clicked");};
// etc....
}
private void buttonClickEvent(object sender, EventArgs e)
{
Button btn = (Button)sender;
if( buttonEventMap.ContainsKey(btn.Name))
buttonEventMap[btn.Name](sender, e);
}
Although this still is't much different from just implementing each individual ButtonClickEvent.

Changing the BackColor of a textbox upon entry

I have the following code for my form:
private void txt1_Enter(object sender, EventArgs e)
{
txt1.SelectAll();
txt1.BackColor = Color.LightBlue;
}
private void txt2_Enter(object sender, EventArgs e)
{
txt2.SelectAll();
txt2.BackColor = Color.LightBlue;
}
private void txt1_Leave(object sender, EventArgs e)
{
txtThermalConductivity.BackColor = Color.White;
}
private void txt2_Leave(object sender, EventArgs e)
{
txtThermalConductivity.BackColor = Color.White;
}
There are another 20 textboxes on my form that I would like to do the same for. Is it possible to combine all of the enter events and all of the leave events so I have two events in total rather than 44 individual events?
In your Designer view, select each textbox and set the Enter and Leave events to point to a single implementation of each.
Then you can do this:
private void txt_enter(object sender, EventArgs e) {
((TextBox)sender).BackColor = Color.LightBlue;
}
private void txt_leave(object sender, EventArgs e) {
((TextBox)sender).BackColor = Color.White;
}
Also, SelectAll isn't required because you're setting the entire textbox's background color.. not the SelectionColor of a RichTextBox.
You could either add manually or iterate over all textboxes in form (extension method found here GetChildControls.
foreach (TextBox textBox in this.GetChildControls<TextBox>())
{
textBox.Enter += new EventHandler(TextBox_Enter);
textBox.Leave += new EventHandler(TextBox_Leave);
}
The above can be called from the Form's Load event.
The event listener now can look like the following by casting the sender to TextBox.
private void TextBox_Enter(object sender, EventArgs e)
{
TextBox txtBox = (TextBox)sender;
txtBox .SelectAll();
txtBox .BackColor = Color.LightBlue;
}
private void TextBox_Leave(object sender, EventArgs e)
{
TextBox txtBox = (TextBox)sender;
txtBox.BackColor = Color.White;
}
It is, just use something like the following:
private void tbLeave(object sender, EventArgs e) {
((TextBox) sender).BackColor = Color.White;
}
The set the controls event declaration to point to this function.
You can also do the same for the Leave() event.
(Just a little note to say, I much prefer to handle this kind of thing client side where possible.)

How can I refactor this C# code below?

I have 12 buttons in my Form1, and each button has a textbox next to it. The button event calls a method called dialogueOpen which handles getting the an object from form2 and placing a string value in a textbox.
How can I place the value returned in a textbox depending on what button the user clicked on? So if it is button1 a user clicked on, then the text returned should be placed in textbox1 and if it is button2 the user clicked on then the text returned should be placed in textbox2. The point is avoid using a string name to check as the buttons can all be called "browse".
Right now my code below does that but it is quite repetitive is there is a better of doing this?
private void dailogueOpen(String btnName)
{
if (listBox1.SelectedItem == null)
{
MessageBox.Show("Please Select a form");
}
else
{
var selectedItem = (FormItems)listBox1.SelectedItem;
var form2result = new Form2(myDataSet, selectedItem);
var resulOfForm2 = form2result.ShowDialog();
if (resulOfForm2 == DialogResult.OK)
{
switch (btnName)
{
case "btn1":
textBox1.Text = form2result.getValue();
break;
case "btn2":
textBox2.Text = form2result.getValue();
break;
case "btn3":
textBox3.Text = form2result.getValue();
break;
case "btn4":
textBox4.Text = form2result.getValue();
break;
case "btn5":
textBox5.Text = form2result.getValue();
break;
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
String name = "btn1";
dailogueOpen(name);
}
private void button2_Click(object sender, EventArgs e)
{
String name = "btn2";
dailogueOpen(name);
}
private void button3_Click(object sender, EventArgs e)
{
String name = "btn3";
dailogueOpen(name);
}
private void button4_Click(object sender, EventArgs e)
{
String name = "btn4";
dailogueOpen(name);
}
private void button5_Click(object sender, EventArgs e)
{
String name = "btn5";
dailogueOpen(name);
}
EDIT: I just noticed your event handlers. More refactoring ensues:
Yes, there is. You need to somehow associate textboxes to buttons. For example, create a dictionary like so:
Dictionary<Button, TextBox> _dict;
_dict[button1] = textBox1;
_dict[button2] = textBox2;
...
Use one event handler for all events:
private void button_click(object sender, EventArgs e)
{
dialogeOpen((Button)sender);
}
Change dialogueOpen to accept a Button instead of a string and
_dict[btn].Text = form2Result.getValue();
replace your eventhandlers to
private void ButtonClick(object sender, EventArgs e)
{
var button = sender as Button;
if (button == null) return;
String name = button.Text;// Tag, name etc
dailogueOpen(name);
}
1 You use the same delegate on all button
Nota (Thank's to Marty) : When You're in the Form Designer, select all buttons, and then assing then "Generic_Click" for all of them, or you can use code below.
this.btn1.Click += new System.EventHandler(Generic_Click); //the same delegate
this.btn2.Click += new System.EventHandler(Generic_Click);
this.btn3.Click += new System.EventHandler(Generic_Click);
....
private void Generic_Click(object sender, EventArgs e)
{
var control = (Button)sender;
if( control.Name == "btn1")
{
....
}
else if( control.Name == "btn2")
{
....
}
else if( control.Name == "btn3")
{
....
}
}
I would first use just one event handler for the buttons, it would look like this:
protected void ButtonClick(object sender, EventArgs e)
{
Button clickedButton = (Button) sender;
string selectedId = clickedButton.ID;
string[] idParameters = selectedId.Split('_');
string textBoxId = "textbox" + idParameters[1];
dailogueOpen(textBoxId);
}
What I did here is use a pattern for the names of the textboxes, so for instance if you have buttons with ids like: button_1 ,button_2, ..., button_n, you can infer what the corresponding textbox is.
If you click button_1, by spliting its id you'll know that its corresponding textbox is the one whose id is textbox1.
Then the dialogueOpen function would look like this:
private void dailogueOpen(string textBoxId)
{
if (listBox1.SelectedItem == null)
{
MessageBox.Show("Please Select a form");
}
else
{
var selectedItem = (FormItems)listBox1.SelectedItem;
var form2result = new Form2(myDataSet, selectedItem);
var resulOfForm2 = form2result.ShowDialog();
if (resulOfForm2 == DialogResult.OK)
{
TextBox textBox = (TextBox)this.Form.FindControl("MainContent").FindControl(textBoxId);
textBox.Text = resulOfForm2.getValue();
}
}
Where MainContent is the id of container where the textboxes are.
All in all:
I would use a pattern for button and texboxes id.
According to the button being clicked I infer its corresponding texbox id.
Then find the texbox and update its value.
You can have dictionary and one event method on all button clicks
Dictionary<Button, TextBox> dx = new Dictionary<Button, TextBox>;
private void ButtonClick(object sender, EventArgs e)
{
var button = sender as Button;
if (button == null) return;
dx[button].Text = form2result.getValue();
}
and constructor like this:
public ClassName()
{
dx.Add(button1, textBox1);
dx.Add(button2, textBox2);
dx.Add(button3, textBox3);
}
I think the first thing you can do is improve readability by removing the need for the switch statement:
private void dailogueOpen(TextBox textBox)
{
if (listBox1.SelectedItem == null)
{
MessageBox.Show("Please Select a form");
}
else
{
var selectedItem = (FormItems)listBox1.SelectedItem;
var form2result = new Form2(myDataSet, selectedItem);
var resulOfForm2 = form2result.ShowDialog();
if (resulOfForm2 == DialogResult.OK)
{
textBox.Text = form2result.getValue();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
dailogueOpen(textBox1);
}
private void button2_Click(object sender, EventArgs e)
{
dailogueOpen(textBox2);
}
private void button3_Click(object sender, EventArgs e)
{
dailogueOpen(textBox3);
}
private void button4_Click(object sender, EventArgs e)
{
dailogueOpen(textBox4);
}
private void button5_Click(object sender, EventArgs e)
{
dailogueOpen(textBox5);
}
This then gives you a reasonable method signature to introduce the dictionary (suggested by two other people) to map Button to TextBox, which would in turn allow you to use a single event handler (suggested by two other people) for all buttons.
private void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (button == null) return;
String name = button.Text;// Tag, name etc
dailogueOpen(name);
}
private void dailogueOpen(String btnName)
{
if (listBox1.SelectedItem == null)
{
MessageBox.Show("Please Select a form");
}
else
{
var selectedItem = (FormItems)listBox1.SelectedItem;
var form2result = new Form2(myDataSet, selectedItem);
var resulOfForm2 = form2result.ShowDialog();
if (resulOfForm2 == DialogResult.OK)
{
SetTxt(btnName,form2result.getValue());
}
}
}
private void SetTxt(string btnName, string value)
{
int lenght = "Button".Length;
string index = btnName.Substring(lenght); //remove Button
TextBox t = (TextBox)this.Controls.Find("textBox" + index, true)[0];
if (t != null)
t.Text = value;
}

Display a message in the font type and size selected by the user from two listboxes

I have been working on this project for a few days, it’s a C# Windows Visual Studio 2010 form and I have been posting different questions that relate to the same project; as I was told to post different questions instead on having them all in the same post. So this is the project: create a form with two ListBoxes—one contains at least four font names and the other contains at least four font sizes. Let the first item in each list be the default selection if the user fails to make a selection. Allow only one selection per ListBox. After the user clicks a button, display "Hello" in the selected font and size.
This time I’m having a problem getting the message in the textbox to display according to the font type and size that the user selected. Here is where I’m at in the coding:
public Form1()
{
InitializeComponent();
//populate listbox1
listBox1.Items.Add("Arial");
listBox1.Items.Add("Calibri");
listBox1.Items.Add("Times New Roman");
listBox1.Items.Add("Verdana");
//populate listbox2
listBox2.Items.Add("8");
listBox2.Items.Add("10");
listBox2.Items.Add("12");
listBox2.Items.Add("14");
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
listBox1.SelectedIndex = 0; // <--- set default selection for listBox1
this.listBox2.SelectedIndexChanged += new System.EventHandler(this.listBox2_SelectedIndexChanged);
listBox2.SelectedIndex = 0; // <--- set default selection for listBox2
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Text = listBox1.SelectedItem.ToString();
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Text = listBox2.SelectedItem.ToString();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.Text = "Hello!";
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
Now I'm trying to elicit a call from a button clicked that will display the message "Hello" in the user’s choice of font and font size. Any suggestions would be greatly appreciated.
remove this method:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.Text = "Hello!";
}
in the button_click event of your button, add this :
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "hello";
textBox1.Font = new Font(listBox1.SelectedItem.ToString(), Convert.ToInt32(listBox2.SelectedItem.ToString()));
}
you might want to remove the selectedindexchanged methods in your code if you are going to use a button tho. depends on what you want.
edit:
public Form2()
{
InitializeComponent();
listBox1.Items.Add("Arial");
listBox1.Items.Add("Calibri");
listBox1.Items.Add("Times New Roman");
listBox1.Items.Add("Verdana");
listBox2.Items.Add("8");
listBox2.Items.Add("10");
listBox2.Items.Add("12");
listBox2.Items.Add("14");
listBox1.SelectedIndex = 0;
listBox2.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "hello";
textBox1.Font = new Font(listBox1.SelectedItem.ToString(), Convert.ToInt32(listBox2.SelectedItem.ToString()));
}
if you just use the above code everything should work as you want it to. I tried it out myself and it's working fine for me
This was my final submission. Thanks for all of the advice guys.
public Form1()
{
InitializeComponent();
//populate listbox1
listBox1.Items.Add("Arial");
listBox1.Items.Add("Calibri");
listBox1.Items.Add("Times New Roman");
listBox1.Items.Add("Verdana");
listBox1.SelectedIndex = 0; // <--- set default selection for listBox1
//populate listbox2
listBox2.Items.Add("8");
listBox2.Items.Add("10");
listBox2.Items.Add("12");
listBox2.Items.Add("14");
listBox2.SelectedIndex = 0; // <--- set default selection for listBox2
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "hello";
textBox1.Font = new Font(listBox1.SelectedItem.ToString(), Convert.ToInt32(listBox2.SelectedItem.ToString()));
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}

Tooltip not showing for nested control

I have the following piece of code that works great in all but one instance.
private void tbxLastName_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
GetRemainingChars(sender);
}
public void GetRemainingChars(object sender)
{
var control = sender as TextEdit;
var maxChars = control.Properties.MaxLength;
tipCharacterCounter.Show(control.Text.Length + "/" + maxChars, this, control.Location.X, control.Location.Y - control.Height);
}
I just repeat this process from any textbox. Unfortunately, I have one control that is more complicated and I cannot get this to work. The Event portion looks like this -->
private void memDirectionsToAddress_Popup(object sender, EventArgs e)
{
MemoExPopupForm popupForm = (sender as DevExpress.Utils.Win.IPopupControl).PopupWindow as MemoExPopupForm;
MemoEdit meDirections = popupForm.Controls[2] as MemoEdit;
meDirections.EditValueChanging += new DevExpress.XtraEditors.Controls.ChangingEventHandler(meDirections_EditValueChanging);
}
void meDirections_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
GetRemainingChars(sender);
}
What I don't understand is if I replace the tipCharacterCounter portion with, say updating a label, it works fine. It's like the ToolTip is hidden or something but I have tried feeding Show() different points to no avail.
Ideas?
Which version of DXPerience are you using? I've tried the following code using DXperience 10.1.5 and it works fine here:
private void memoExEdit1_Popup(object sender, EventArgs e) {
MemoExPopupForm popupForm = (sender as DevExpress.Utils.Win.IPopupControl).PopupWindow as MemoExPopupForm;
MemoEdit meDirections = popupForm.Controls[2] as MemoEdit;
meDirections.EditValueChanging += new DevExpress.XtraEditors.Controls.ChangingEventHandler(meDirections_EditValueChanging);
}
void meDirections_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e) {
GetRemainingChars(sender);
}
public void GetRemainingChars(object sender) {
TextEdit control = sender as TextEdit;
int maxChars = control.Properties.MaxLength;
tipCharacterCounter.ShowHint(control.Text.Length + "/" + maxChars, control, ToolTipLocation.RightBottom);
}

Categories

Resources