I have three radio buttons. The code behind their change events is as follows:
private void uxRajRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxRajRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Raj";
GuySelected = 0;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
private void uxPaulRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxPaulRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Paul";
GuySelected = 1;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
private void uxMikeRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxMikeRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Mike";
GuySelected = 2;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
With just three radio buttons this is acceptable but if I had say 7 radio buttons each with 20 lines of code behind its change event then it would be a lot of (needless?) code. I've attempted to shorten the above and ended up with the following. Is this correct?
private void uxRajRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxRajRadioButton, 0);
}
private void uxPaulRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxPaulRadioButton,1);
}
private void uxMikeRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxMikeRadioButton, 2);
}
int GuySelected=0;
public void radioButtonCode(RadioButton myRadio, int mybettorIndex)
{
if (myRadio.Checked == true)
{
GuySelected = mybettorIndex;
uxPersonBettingLabel.Text = Guys[GuySelected].Name;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
Could you have the same event handler for all the radio buttons? Something like
private void uxRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode((RadioButton)sender);
}
public void radioButtonCode(RadioButton myRadio)
{
if (myRadio.Checked == true)
{
int guySelected = getGuySelectedIndex(myRadio);
uxPersonBettingLabel.Text = Guys[guySelected].Name;
uxBetNumericUpDown.Maximum = Guys[guySelected].Cash;
}
}
public int getGuySelectedIndex(RadioButton myRadio)
{
int index = 0;
if (myRadio == this.uxRajRadioButton) index = 0;
else if (myRadio == this.uxPaulRadioButton) index = 1;
else if (myRadio == this.uxMikeRadioButton) index = 2;
return index;
}
Your second code sample, where you have extracted the commonalities out to a function looks like the way I would have done this refactoring.
It is about as good as you can make it, barring the name (UpdateUserInfo might be slightly better).
There is a better way. Declare an array of radio buttons and bind them to above event at run time. This binding code won't be inside designer page. This will result in single ArrayRadio_checkedChange event. In this method you can use sender property to figure out the proper radio button's index and take action accordingly.
you can use
uxRajRadioButton.CheckedChanged += new EventHandler(rb_CheckedChanged);
uxPaulRadioButton.CheckedChanged += new EventHandler(rb_CheckedChanged);
...
uxRajRadioButton.Tag =new KeyValuePair<string,int>("Raj",0);
uxPaulRadioButton.Tag =new KeyValuePair<string,int>("Paul",1);
....
private void rb_CheckedChanged(object sender, EventArgs e)
{
if(!(sender is RadioButton))
return;
RadioButton myRadio= sender as RadioButton;
if (myRadio.Checked == true)
{
myRadio.Text = (myRadio.Tag as KeyValuePair<string,int>).Key;
GuySelected = (myRadio.Tag as KeyValuePair<string,int>).Value;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
What I usually do is I put the index in the tag attribute. This way you can bind this event to every RadioButton
public void uxRadioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton myRadio = (RadioButton) sender;
if (myRadio.Checked)
{
GuySelected = (int)myRadio.Tag;
uxPersonBettingLabel.Text = Guys[GuySelected].Name;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
Related
Let's say I have a ListView on a form and it is populated with records.
How can I do this : when I click (single click) on a row , something has to happen - for example MessageBox.Show("row selected");
How to make this happen? Do I need a mouse click event ? And how can I do this?
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedItemText = (listBox1.SelectedItem ?? "(none)").ToString();
MessageBox.Show("Selected: " + selectedItemText);
}
private void listBox1_MouseClick(object sender, MouseEventArgs e)
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
var rectangle = listBox1.GetItemRectangle(i);
if (rectangle.Contains(e.Location))
{
MessageBox.Show("Item " + i);
return;
}
}
MessageBox.Show("None");
}
#Tommy answer is for ListBox, this one is for ListView :
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
for (int i = 0; i < listView1.Items.Count; i++)
{
var rectangle = listView1.GetItemRect(i);
if (rectangle.Contains(e.Location))
{
//Write your code here
return;
}
}
}
To prevent unwished behavior on ListView with checkboxes my solution is:
private void lvMembers_MouseClick(object sender, MouseEventArgs e)
{
for (int itemIndex = 0; itemIndex < lvMembers.Items.Count; itemIndex++)
{
ListViewItem item = lvMembers.Items[itemIndex];
Rectangle itemRect = item.GetBounds(ItemBoundsPortion.Label);
if (itemRect.Contains(e.Location))
{
item.Checked = !item.Checked;
break;
}
}
}
If you want to select listview item on mouse click over it try this.
private void timeTable_listView_MouseUp(object sender, MouseEventArgs e)
{
Point mousePos = timeTable_listView.PointToClient(Control.MousePosition);
ListViewHitTestInfo hitTest = timeTable_listView.HitTest(mousePos);
try
{
int columnIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);
edit_textBox.Text = timeTable_listView.SelectedItems[0].SubItems[columnIndex].Text;
}
catch(Exception)
{
}
}
I have 40 buttons that all do something slightly different when clicked, I would like to condense this down if I can. I also want to say, if one of the buttons is clicked, create a timestamp which can be accessed by the class.
Here is the code for 2 out of 40 of the buttons:
private void Btn1_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 5; i++)
{
CheckBox CheckBox = (this.FindName(string.Format("Check{0}", i)) as CheckBox);
if (CheckBox != null)
{
CheckBox.IsChecked = true;
}
}
}
private void BtnDisable1_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 5; i++)
{
CheckBox CheckBox1 = (this.FindName(string.Format("Check_D{0}", i)) as CheckBox);
if (CheckBox1 != null)
{
CheckBox1.IsChecked = false;
}
}
}
I think one way of doing it is putting it in an array and whenever one of the 40 buttons are clicked it looks in the array on what to do next? I'm not really sure, thank you!
You can make this simple using one method.
Answer is updated based on this discussion
private void DoWork(int checkboxGroup, bool enable)
{
int start = checkboxGroup * 4;
for (int i = start; i < start + 4; i++)
{
CheckBox CheckBox = this.FindName("CheckBox" + i) as CheckBox;
if (CheckBox != null)
{
CheckBox.IsChecked = enable;
}
}
}
private void Btn1_Click(object sender, RoutedEventArgs e)
{
DoWork(1 , true);
}
private void BtnDisable1_Click(object sender, RoutedEventArgs e)
{
DoWork(1 , false);
}
Because there are 40 methods like this you can use Expression bodied methods. You must have C#6 to use this feature.
private void Btn1_Click(object sender, RoutedEventArgs e) => DoWork(1 , true);
private void BtnDisable1_Click(object sender, RoutedEventArgs e) => DoWork(1 , false);
private void Btn2_Click(object sender, RoutedEventArgs e) => DoWork(2, true);
private void BtnDisable2_Click(object sender, RoutedEventArgs e) => DoWork(2, false);
// and so on
I have a C# winforms application and I am trying to get a button working that will select the next row in a datagridview after the one curently selected.
The code I have so far is:
private void button4_Click(object sender, EventArgs e)
{
try
{
Int32 selectedRowCount = dataGridView1.Rows.GetRowCount(DataGridViewElementStates.Selected);
// index out of range on this line
dataGridView1.Rows[dataGridView1.SelectedRows[selectedRowCount].Index].Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = selectedRowCount + 1;
}
catch (Exception ex)
{
return;
}
But on running this it throws an exception. Could anyone point out where I may be going wrong. The thrown error is: Index is out of range
try this:
int nRow;
private void Form1_Load(object sender, EventArgs e)
{
nRow = dataGridView1.CurrentCell.RowIndex;
}
private void button1_Click(object sender, EventArgs e)
{
if (nRow < dataGridView1.RowCount )
{
dataGridView1.Rows[nRow].Selected = false;
dataGridView1.Rows[++nRow].Selected = true;
}
}
First, set "Multiselect" property of datagridview to false.
int currentRow = dataGridView1.SelectedRows[0].Index;
if (currentRow < dataGridView1.RowCount)
{
dataGridView1.Rows[++currentRow].Selected = true;
}
It will select the next row in the datagridview.
Select Row and Cell for better solution.
This solution move row indicator on DataGridView.
private void _GotoNext(object sender, EventArgs e)
{
int currentRow = DataGridView1.SelectedRows[0].Index;
if (currentRow < DataGridView1.RowCount - 1)
{
DataGridView1.Rows[++currentRow].Cells[0].Selected = true;
}
}
private void _GotoPrev(object sender, EventArgs e)
{
int currentRow = DataGridView1.SelectedRows[0].Index;
if (currentRow > 0)
{
DataGridView1.Rows[--currentRow].Cells[0].Selected = true;
}
}
It's here:
dataGridView1.SelectedRows[selectedRowCount]
If you have 3 selected rows then selectedRowCount = 3 and there are three rows with indexes: 0, 1, 2.
You are trying to access #3 which doesn't exist.
this example to read value cell or column is number 4 of datagridview
int courow = dataGridView1.RowCount-1;
for (int i=0; i < courow; i++)
{
MessageBox.Show(dataGridView1.Rows[i].Cells[4].Value.ToString());
}
I prefer this row selection :
First check if no multiselect : number_of_data
Then get the select cell (or row) : row_index
private void next_click(object sender, EventArgs e)
{
int number_of_data = dataGridView.SelectedRows.Count;
if (number_of_data > 1) return;
int row_index = dataGridView.SelectedCells[0].RowIndex;
if (row_index < dataGridView.RowCount-1)
{
dataGridView.Rows[row_index++].Selected = false;
dataGridView.Rows[row_index].Selected = true;
}
// Do something
}
enter code here private void Form1_Load(object sender, EventArgs e)
{
X = dataGridView1.CurrentCell.RowIndex;//int x;
}
enter code here private void button2_Click(object sender, EventArgs e)
{
if (dataGridView1.Rows.Count > 0)
{
this.dataGridView1.ClearSelection();
dataGridView1.Rows[0].Selected = true;
}
}
enter code here private void button3_Click(object sender, EventArgs e)
{
if (X < dataGridView1.RowCount)
{
if (X != dataGridView1.RowCount - 1)
{
dataGridView1.ClearSelection();
dataGridView1.Rows[++X].Selected = true;
}
else
{
button2_Click(sender, e);//this else with make it loop
X = 0;
}
}
}
dgv_PhotoList.Rows[dgv_PhotoList.CurrentRow.Index+1].Selected = true;
I have two text box and i want to calculate each text box when the other changed.but my program fall into a loop.
private bool suspendEvents = false;
private void txtYourPercent_ValueChanged(object sender, EventArgs e)
{
if (suspendEvents)
return;
suspendEvents = true;
txtMyPercent.value = 100 - txtYourPercent.value;
suspendEvents = false;
}
private void txtMyPercent_ValueChanged(object sender, EventArgs e)
{
if (suspendEvents)
return;
suspendEvents = true;
txtYourPercent.value = 100 - txtMyPercent.value;
suspendEvents = false;
}
It's my way.This method is disgusting.Any better solution? ("WinForms")
If there is not another solution tell me to delete this question and use my (beep) solution.
You could assign both textboxes the same chenge event handler:
this.txtMyPercent.TextChanged += new System.EventHandler(this.txtPercent_TextChanged);
this.txtYourPercent.TextChanged += new System.EventHandler(this.txtPercent_TextChanged);
and then:
private void txtPercent_TextChanged(object sender, EventArgs e)
{
if (sender == txtMyPercent)
{
txtYourPercent.Text = (100 - int.Parse(txtMyPercent.Text)).ToString();
}
else if (sender == txtYourPercent)
{
txtMyPercent.Text = (100 - int.Parse(txtYourPercent.Text)).ToString();
}
}
Im trying to create a array of Checkboxes in Winforms and I have four Checkboxes and if I click on a Checkbox, a messagebox should display the checkboxes checked.
public void checkboxtest()
{
CheckBox[] boxes = new CheckBox[4];
boxes[0] = checkBox1;
boxes[1] = checkBox2;
boxes[2] = checkBox3;
boxes[3] = checkBox4;
for (int i = 0; i <= 4; i++)
{
if (boxes[i].Checked == true && boxes[i].Enabled)
{
MessageBox.Show("boxes[i] is clicked");
}
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkboxtest();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
checkboxtest();
}
continues for 3 and 4 too...
How should I go about it ??
Thanks.
Your loop termination should be i < 4, not i <= 4 since your array only has 4 elements. Also boxes[i].Checked == true is redundant, you can just say boxes[i].Checked.
If you want to display the checked checkboxes when you toggle the state, you'll need to add an event handler to them (to handle the CheckBox.CheckChanged event):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_checkBoxes = new CheckBox[] { _checkBox1, _checkBox2, _checkBox3, _checkBox4 };
foreach (var checkBox in _checkBoxes)
checkBox.CheckedChanged += new EventHandler(ShowCheckedCheckboxes);
}
void ShowCheckedCheckboxes(object sender, EventArgs e)
{
string message = string.Empty;
for (int i = 0; i < _checkBoxes.Length; i++)
{
if (_checkBoxes[i].Checked && _checkBoxes[i].Enabled)
{
message += string.Format("boxes[{0}] is clicked\n", i);
}
}
MessageBox.Show(message);
}
CheckBox[] _checkBoxes;
}