Verify which dynamically created Radiobutton is checked in C# - c#

I am developing an application with multiple Panels (eight, to be precise) on one Form. In each Panel there are one TableLayoutPanel with three Radiobuttons (among of few other unimportant components). The Radiobuttons set the priority of the specific Panel's input (Priority 1, 2 and 3).
I have no intention of placing three Radiobuttons on each of the eight Panels as I believe there are more effective ways of doing this. Below is the code used to place the Radiobuttons:
private void AddPriorityRadBtn(TableLayoutPanel lLayoutTable, int lTableLayoutColumn, int lTableLayoutRow)
{
int lPriority = -1;
try
{
for (int i = lTableLayoutRow; i < (lTableLayoutRow+ 3); i++)
{
RadioButton lRadBtn = new RadioButton();
lPriority = i - lLayTblStRow + 1;
lRadBtn.Name = "radP_" + lPriority.ToString();
lRadBtn.Text = "Priority Level " + lPriority.ToString();
lRadBtn.Anchor = AnchorStyles.Left;
lLayoutTable.Controls.Add(lRadBtn);
if (lPriority < 3)
{
lRadBtn.Checked = false;
}
else if(lPriority == 3)
{
lRadBtn.Checked = true;
}
lTableLayout.Controls.Add(lRadBtn, lTableLayoutColumn, i);
}
}
catch
{
Console.WriteLine(ex);
}
}
The lTableLayoutColumn and lTableLayoutRow are used to set the column in which the Radiobuttons are placed. lPriority are used to calculate the Priority of the button and always has a value from 1 to 3.
I can add the Radiobuttons with the above code. I suspect this is where the problem is.
The next piece of code is where the problem becomes more evident:
private int GetSelectedRadioBtn()
{
RadioButton lRadBtnPriority = new RadioButton();
try
{
for (int i = 1; i < 4; i++)
{
lRadBtnPriority.Name = "radP_" + i.ToString();
if (lRadBtnPriority.Checked == true)
{
return i;
}
}
return -1;
}
catch (Exception ex)
{
return -1;
}
}
This function always returns -1 from the try block. Thus my application can't see which one of the Radiobuttons is selected.
What would be the reason for this? Any kind of help would be much appreciated.

Your GetSelectedRadioBtn() creates its own radio button how is it supposed to be linked to the previous buttons?
lRadBtnPriority.Name = "radP_" + i.ToString();
doing this doesnt magicly link your new button to the previusly created ones.
One way of doing what you want to do is subscribing a checkedChanged event to the radio buttons and changing a global variable called selectedRadio.
for (int i = lTableLayoutRow; i < (lTableLayoutRow+ 3); i++)
{
RadioButton lRadBtn = new RadioButton();
lPriority = i - lLayTblStRow + 1;
lRadBtn.Name = "radP_" + lPriority.ToString();
lRadBtn.Text = "Priority Level " + lPriority.ToString();
lRadBtn.Anchor = AnchorStyles.Left;
lRadBtn.Tag = i;
lRadBtn.CheckedChanged +=(ss,ee)=>{
selectedRadio = (int)((RadioButton)ss).Tag;
};
lLayoutTable.Controls.Add(lRadBtn);
if (lPriority < 3)
{
lRadBtn.Checked = false;
}
else if(lPriority == 3)
{
lRadBtn.Checked = true;
}
lTableLayout.Controls.Add(lRadBtn, lTableLayoutColumn, i);
}
then in GetSelectedRadioBtn you do this
private int GetSelectedRadioBtn()
{
return selectedRadio;
}

The easiest way to do it is to store a reference to the radio buttons created in the AddPriorityRadBtn. You can keep them for example, in a dictionary which uses the Panel as key, and the three radio buttons in an array.
Then, you just have to look at the dictionary to recover the radio buttons and check its state.

Related

Fill an array with a loop

I want to get a shorter code than now but I don't know how.
What I do now is like the code below.
arrPictureBox[0] = picChair0;
arrPictureBox[1] = picChair1;
arrPictureBox[2] = picChair2;
arrPictureBox[3] = picChair3;
arrPictureBox[4] = picChair4;
arrPictureBox[5] = picChair5;
arrPictureBox[6] = picChair6;
arrPictureBox[7] = picChair7;
arrPictureBox[8] = picChair8;
arrPictureBox[9] = picChair9;
arrPictureBox[10] = picChair10;
arrPictureBox[11] = picChair11;
(pic) is a picturebox.
But I want less code but I don't know if it possible to do this with a loop (for loop).
for (int i = 0 ; i < arrPictureBox.Length; i++)
{
arrPictureBox[i] = picChair + i;
}
If picChairN is a local variable then there's nothing you can do to simplify it as much as you'd like. The best you can do is
arrPictureBox = new [] { picChair0, picChair1, picChair2, picChair3,
picChair4, picChair5, picChair6, picChair7,
picChair8, picChair9, picChair10, picChair11};
If picChairN is a class member (e.g. a field created by the designer) then you could use reflection, but considering you already have the array method typed out I don't see much benefit.
Let's predict you're on WinForms and the pictureBoxes already exist, then you can use the following:
for (int i = 0; i < arrPictureBox.Length; i++)
{
arrPictureBox[i] = this.Controls["picChair" + i];
}
Which actually does this:
get the first Control (a PictureBox for example) with the given name
add the found control to the array of pictureboxes
EDIT:
It might be useful to check for non existing pictureBoxes:
for (int i = 0 ; i < arrPictureBox.Length; i++)
{
var pb = this.Controls["picChair" + i] as PictureBox;
if (pb != null)
{
arrPictureBox[i] = pb;
}
}
You can use al List like below.
List<string> arrPictureBox = new List<string>();
for (int i = 0; i < 20; i++)
{
arrPictureBox.Add("picChair" + i);
}
var result = arrPictureBox.ToArray();
Hope it helps.
If all the picture boxes are on the same form and are the ONLY picture boxes on the form, you can loop through them with something like the following:
int x = 0;
foreach(Control c in this.Controls)
{
if(c is PictureBox)
{
arrPictureBox[x++] = c
}
}

No error but something is wrong with DataGridView

I roughly translated vb.net code to c# for a simple POS system i'm coding for school. But when i try to add things to the datagrid using button click event there is no change in the datagrid. there are no errors. the datagrid is not connected to a database, at least not yet.
here's the code where i insert things to the datagrid:
private void txtAdd_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
{
var with = dataSales;
int ii = 0;
int orderproduct = 0;
int count = 0;
for (ii = 0; ii <= with.RowCount - 1; ii++)
{
if (txtProduct.Text == Convert.ToString(dataSales[0, ii].Value))
{
count = count + 1;
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
else
{
if (count == 0)
{
float sum = Convert.ToInt32(txtPrice.Text) * Convert.ToInt32(txtQuantity.Text);
dataSales.Rows.Add(txtProduct.Text, txtPrice.Text, txtQuantity.Text, sum);
count = 0;
}
txtProduct.Clear();
txtQuantity.Clear();
txtPrice.Clear();
}
}
else
{
MessageBox.Show("Nothing is Selected", "Error");
}
}
}
}
Follow your counter and you will understand why you never get anything added. You start with 0 but add +1 every single time there is text to add. PUt it in debug and watch.
EDITED: Due to your comment you do not know how to debug. Open the .cs file in Visual Studio, Click on the left margin for the line that tests for text in the fields (the line below):
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
Now start the program, enter text and run it. It will stop on that line. You can then hit F11 and it will go to the line that increments the counter. This means you will always run this branch.
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
NOTE: You do not need this:
if (count == 0)
{
}
Why? You have already sent anything not 0 to the other branch. The else is sufficient at this point, and no need to waste a cycle determining if something that will ALWAYS be zero is zero

Checkbox name with For counter

I have this loop and multiple leds. The names of the leds are Led0, Led1, Led2 etc
Now i want to change the background of each Led with this loop so i use the counter iTeller.
I use WPF and only work in the mainwindow.
for (int iTeller = 0; iTeller < bits.Count(); iTeller++)
{
if (bits[iTeller] == 1)
{
//this doesn't work
*Led+iTeller+.Background = Brushes.Green;*
}
}
Try Like This (WPF)
for (int iTeller = 0; iTeller < bits.Count(); iTeller++)
{
if (bits[iTeller] == 1)
{
object i = this.FindName("Led" & iTeller);
if (i is CheckBox)
{
CheckBox k = (CheckBox)i;
MessageBox.Show(k.Name);
}
}
}
This will not work for a lot of reasons. The first is, that your leds are some type of control, which you need in a variable, you cannot simply call them like this.
Do you use WPF or Winforms?
You need a list of your leds, then you can iterate over the list and assign the value to each led
You cannot resolve a variable name like this, you can use the Find method (at least in Windows Forms), to find a named control.
You can also store the controls in an array, that way you prevent using relatively slow Find calls and other error checking:
var leds = new CheckBox[] { Led0, Led1, Led2, Led3, Led4, Led5, Led6, Led7 };
for (int iTeller = 0; iTeller < bits.Count(); iTeller++)
{
if (bits[iTeller] == 1)
{
leds[iTeller].Background = Brushes.Green;
}
}
This worked
for (int iTeller = 0; iTeller < bits.Count(); iTeller++)
{
if (bits[iTeller] == 1)
{
var myCheckbox = (CheckBox)this.FindName("Led" + iTeller);
myCheckbox.Background = Brushes.Green;
}
}
Thanks everyone

Remove Rows from TableLayoutPanel [duplicate]

I'm currently trying to fill a TableLayoutPanel through a method which goes as follows:
private int _rowCount;
public void InitPaths()
{
int c = 1;
int a = 1;
while (a < _PathRows.Length - 1)
{
var label = new Label();
//
// Label - Format.
//
label.Dock = DockStyle.Fill;
label.AutoSize = false;
label.Text = _pfadZeilen[a];
label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
label.Size = new System.Drawing.Size(22, 13);
label.BackColor = System.Drawing.Color.Transparent;
TableLayoutP.Controls.Add(label, 3, c);
//Checkboxen Einfügen
var cbox = new CheckBox();
//
//Checkbox Format.
cbox.Anchor = System.Windows.Forms.AnchorStyles.None;
cbox.AutoSize = true;
cbox.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.Name = "checkBoxPfad" + a;
cbox.Size = new System.Drawing.Size(15, 14);
cbox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.UseVisualStyleBackColor = true;
TableLayoutP.Controls.Add(cbox, 0, c);
a++;
c++;
}
this._rowCount = BibTable.GetRowHeights().Length; // which seems to be Holding the value only within the method
}
and then delete all rows on Action, through the following Method:
public void RemoveRows()
{
for (int row = _rowCount; row >= 0; row--)
{
BibTable.RowStyles.RemoveAt(row);
BibTable.RowCount--;
}
}
Now the Problem is, if I try to do anything with the TableLayoutP outside of the method where all rows are initialized, it will tell me:
Object reference not set to the instance of an object.
What can I do? Is there a way to get a method inside a method (I'm realising just how stupid that sounds while typing it) or any other way to deal with this Situation?
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();

C#: How would you cycle through items in a listview using next and previous buttons?

C#: How would you cycle through items in a listview using next and previous buttons?
Background:
Let's say you have 10 items in a listview.
Next to the listview there are two buttons titled previos and next.
Problem:
How would you cycle through those listview items after clicking the Next and or Previous button?
If you just want to select the next item (so with items a, b, c, go from b selected to c selected), you can do this:
if (listView.SelectedIndices.Count > 0)
{
int oldSelection = listView.SelectedIndices[0];
listView.SelectedIndices.Clear();
if (oldSelection + 1 >= listView.Items.Count)
listView.SelectedIndices.Add(0);
else
listView.SelectedIndices.Add(oldSelection + 1);
}
I think you are saying that you want to implement paging?
If so, just keep a record of your current page number in index and when the next button is clicked, increment the page number, retrieve that page's worth of records and bind that to the list.
There is an automatic way of doing this if you implement data providers and such. Check the documentation on ListView on how this is done. You will need to give the button a special "Action" for it to work.
For more info:
http://msdn.microsoft.com/en-us/library/bb515102.aspx
//UpOrDown is a +1 or -1
void Page(int UpOrDown){
//Determine if something is selected
if (listView.SelectedIndices.Count > 0)
{
int oldIndex = listView.SelectedIndices(0);
listView.SelectedIndices.Clear();
//Use mod!
int numberOfItems = listView.Items.Count();
listView.SelectedIndices.Add((oldIndex + UpOrDown) % numberOfItems)
}
}
Using modulus division, I feel like people have forgot about this guy
int oldSelection = ListView1.SelectedIndices[0];
if(*NextOptionSelected* && oldSelection + 1 < ListView1.Items.Count)
{
ListView1.Items[oldSelection + 1].Selected = true;
ListView1.Items[oldSelection + 1].Focused = true;
ListView1.Items[oldSelection].Selected = false;
ListView1.Items[oldSelection].Focused = false;
}
else if(*LastOptionSelected* && oldSelection > 0)
{
ListView1.Items[oldSelection - 1].Selected = true;
ListView1.Items[oldSelection - 1].Focused = true;
ListView1.Items[oldSelection].Selected = false;
ListView1.Items[oldSelection].Focused = false;
}
ListView1.EnsureVisible(ListView1.SelectedIndices[0]);
put +1 for next and -1 for prev data
here is the code:-
Dim CurrentRow As Integer
CurrentRow = Form2.ListView1.Items.IndexOf(Form2.ListView1.FocusedItem)
CurrentRow =CurrentRow + 1
Form2.ListView1.Items(CurrentRow).Selected = True
Form2.ListView1.Items(CurrentRow).Focused = True
This is the vb code to move to the next row in listview
1.Add the listview control to form
2.Add one button to form
3.Double click that button and right the above code
tested aproach using Page method, null/out of index range-proof:
private void Page(int UpOrDown, ListView list)
{
//Determine if something is selected
list.Focus();
if (list.SelectedIndices.Count == 0)
{
if (list.Items.Count > 0)
{
list.Items[0].Selected = true;
list.SelectedIndices.Add(0);
list.Items[0].Focused = true;
list.EnsureVisible(list.Items[0].Index);
list.TopItem = list.Items[0];
}
}
if (list.SelectedIndices.Count > 0)
{
if (list.SelectedIndices[0] == null)
{
list.SelectedIndices.Add(0);
}
int oldIndex = list.SelectedIndices[0];
list.SelectedIndices.Clear();
//Use mod!
int numberOfItems = list.Items.Count;
if (oldIndex + UpOrDown >= 0 && oldIndex + UpOrDown <= list.Items.Count-1)
{
list.SelectedIndices.Add((oldIndex + UpOrDown)%numberOfItems);
list.SelectedItems[0].Selected = true;
list.SelectedItems[0].Focused = true;
list.EnsureVisible(list.SelectedItems[0].Index);
//list.TopItem = list.SelectedItems[0];
}
}
}
Without testing it, I'm guessing this would work:
for(int i=0;i<listView.Items.Count;i++)
listView.Items[i]

Categories