How can I refactor this C# code below? - c#

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;
}

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.

How to make one event to identify whether multiple radio buttons are checked?

I have the following code which checks each radio button (Temp30, Temp40 and Temp60) and does the necessary things such as turning the wash temperature light on etc...
I want to create an event which handles all 3 radio buttons. I thought it could possibly have something to do with the groupbox they are in? (it is called TempGroupBox)
Any help would be much appreciated!
private void Temp30_CheckedChanged(object sender, EventArgs e)
{
if (Temp30.Checked)
{
MainDisplayLabel.Text = (" SELECT SPIN SPEED");
WashTempLight.Visible = true;
WashTempLight.Image = Properties.Resources._30degrees;
SpeedGroupBox.Enabled = true;
}
}
private void Temp40_CheckedChanged(object sender, EventArgs e)
{
if (Temp40.Checked)
{
MainDisplayLabel.Text = (" SELECT SPIN SPEED");
WashTempLight.Visible = true;
WashTempLight.Image = Properties.Resources._40degrees;
SpeedGroupBox.Enabled = true;
}
}
private void Temp60_CheckedChanged(object sender, EventArgs e)
{
if (Temp60.Checked)
{
MainDisplayLabel.Text = (" SELECT SPIN SPEED");
WashTempLight.Visible = true;
WashTempLight.Image = Properties.Resources._60degrees;
SpeedGroupBox.Enabled = true;
}
}
You can bind all radioButton's event to the same handler and use sender parameter to get the control that the action is for.
private void Temps_CheckedChanged(object sender, EventArgs e)
{
string checkedName = ((RadioButton)sender).Name;
if(checkedName == "Temp40")
{
...
}
else if(checkedName == "Temp60")
{
...
}
}
You can add event handler for all RadioBUttons's like that after InitializeComponent():
var radioButtons =this.Controls.OfType<RadioButton>();
foreach (RadioButton item in radioButtons)
{
item.CheckedChanged += Temps_CheckedChanged;
}

How to get the text from current cell in datagridview textchanged event?

i am making a windows form application in which i used a datagridview.
i want that when i write something in textbox in datagridview,than a messagebox appears containing the string i wrote..
ican't get my text in textchanged event..
all thing must be fired in textchanged event..
here is my code:-
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView1.CurrentCell.ColumnIndex == 1)
{
TextBox tb = (TextBox)e.Control;
tb.TextChanged += new EventHandler(tb_TextChanged);
}
}
void tb_TextChanged(object sender, EventArgs e)
{
//listBox1.Visible = true;
//string firstChar = "";
//this.listBox1.Items.Clear();
//if (dataGridView1.CurrentCell.ColumnIndex == 1)
{
string str = dataGridView1.CurrentRow.Cells["Column2"].Value.ToString();
if (str != "")
{
MessageBox.Show(str);
}
}
void tb_TextChanged(object sender, EventArgs e)
{
var enteredText = (sender as TextBox).Text
...
}
Showing MessageBox in TextChanged will be very annoying.
Instead you could try it in DataGridView.CellValidated event which is fired after validation of the cell is completed.
Sample code:
dataGridView1.CellValidated += new DataGridViewCellEventHandler(dataGridView1_CellValidated);
void dataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
{
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
}
}

C# combobox if statement + continue button incorporation

This code doesn't work. I don't know what to fix.
public sealed partial class Home : Page
{
public Home()
{
this.InitializeComponent();
ComboBox1.Items.Add("Hindiiiii");
}
string selection = null;
private void ComboBox1_SelectedIndex(object sender, EventArgs e)
{
if (ComboBox1.SelectedIndex!=1)
{
selection = ComboBox1.SelectedItem.ToString();
}
}
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
{
if (selection == "Hindiiiii")
this.Frame.Navigate(typeof(MainPage));
else if (selection == "English")
this.Frame.Navigate(typeof(Home));
}
}
When a user selects Hindiiiii on the main screen and clicks continues he is not redirected to the next page (MainPage).
Let's say your main page looks like this:
You can store the selection in a variable:
string selection = null;
private void ComboBox1_SelectedIndex(object sender, EventArgs e)
{
if (ComboBox1.SelectedIndex!=-1)
{
selection = ComboBox1.SelectedItem.ToString();
}
}
Then in your click event you can pass parameters between your pages:
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
this.Frame.Navigate(typeof(SomePage), selection); //send the contents of the variable to another page
}
And let's say you had another page with a TextBox and a TextBlock:
In your other pages' OnNavigatedTo event, you can retrieve the parameters so you don't have to create a page for every selected language:
string selection = null;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
selection = e.Parameter.ToString();
languageTextBlock.Text = selection; //the textblox is now the selected language
//decide what the contents are based on the selection
if (selection == "English")
translation.Text = "Something in English";
else if (selection == "Hindi")
translation.Text = "Something in Hindi";
else if (selection == "German")
translation.Text = "Something in German";
//etc
}
When you go to the next page, this allows you to create your page based on the selected item. This image demonstrates this:
Alternatively, you can solve your problem by creating a page for every possible language:
private void Continue(object sender, RoutedEventArgs e)
{
if(selection != null)
{
if(selection == "English")
this.Frame.Navigate(typeof(EnglishPage));
else if(selection == "Hindi")
this.Frame.Navigate(typeof(HindiPage));
//and so on
}
}
I prefer to do it this way because it's a lot simpler.
Edit: I see Items in the property box but I'm not aware of how to use it to add combo box items. This is the way that I usually see it done:
Of course you'll need to replace MainPage with your page (if it's not already named MainPage).
Another edit:
If you added the items via the properties panel, you have to access the Content. Use this instead, if you want:
string selection = null;
private void ComboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ComboBox1.SelectedIndex != -1)
{
//selection = ComboBox1.SelectedItem.ToString();
selection = (ComboBox1.SelectedItem as ComboBoxItem).Content.ToString();
}
}

Clear listbox when new tab selected

I am trying to clear the contents of a listbox when a new tab is seleced. Here is what I got, but nothing happens.
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabControl1.TabPages["entryTab"])
{
readBox.Items.Clear();
reminderBox.Items.Clear();
}
}
Try something like this in your form load
tabControl1.Selecting += new TabControlCancelEventHandler(tabControl1_SelectedIndexChanged);
// Try this set null to DataSource
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabControl1.TabPages["entryTab"])
{
readBox.DataSource = null;
reminderBox.DataSource = null;
}
}

Categories

Resources