I am making a DTO creator. I am able get the table names and put them into datatable. The problem is, I must create checkboxes dynamically using these table names, and then be able to get whatever items checked. This is what I have been able to come up with so far:
for (int i = 0; i < dtable.Rows.Count; i++)
{
string cbName = dtable.Rows[i][0].ToString();
//Console.WriteLine(dtable.Rows[i][0]);
CheckBox box = new CheckBox();
box.Tag = i.ToString();
box.Text = cbName;
box.AutoSize = true;
box.Location = new Point(10, i * 50); //vertical
//box.Location = new Point(i * 50, 10); //horizontal
this.Controls.Add(box);
}
The dtable already has names and I create the checkboxes. However they are out the rendered area of the form, can see at most 10 of them. Also, how can I register which boxes are checked during runtime?
You can either put your CheckBoxes in a List and then count the checked ones.
List<CheckBox> lstBoxes = new List<CheckBox>();
// create box
...
lstBoxes.Add(box);
// Checking for checked boxes (eg. on form exit)
var checkedBoxes = lstBoxes.Where(b => b.Checked);
Or when you're creating your checkboxes, add an event on checked changed :
box.CheckedChanged += (sender, e) =>
{
var senderAsBox = sender as CheckBox;
if (senderAsBox == null) return;
var state = senderAsBox.Checked;
// Do you stuff then...
};
Related
My application is running unstable because I have to many checkboxes in one form. I heard from some source, that I should try to populate the checkboxes in a CheckedListBox. But I dont know how i can realize that. Among I wanna show you my solution with CheckBox.
Can anyone show me how I can populate this with a CheckedListBox?
for (int i = 1; i <= maxTask; i++)
{
Label labelTasks = new Label();
labelTasks.Text = "A" + i;
labelTasks.Width = 28;
labelTasks.Height = 13;
labelTasks.Location = new Point(boundX_Label, boundY_Label);
boundX_Label += 26;
panel.Controls.Add(labelTasks);
CheckBox checkBox = new CheckBox();
checkBox.Name = String.Format("checkboxTask{0}", i);
checkBox.GotFocus += checkBox_GotFocus;
checkBox.LostFocus += checkBox_LostFocus;
checkBox.Text = "";
checkBox.Width = 20;
checkBox.Height = 15;
checkBox.Location = new Point(boundX_ChkBox, boundY_ChkBox);
boundX_ChkBox += 26;
checkBox.CheckedChanged += new EventHandler(checkBox_CheckedChanged);
panel.Controls.Add(checkBox);
}
This code will populate a row of checkboxes like showing among. My application have around 200 of this checkbox rows.
You can use a CheckedListBox for this, you can add items to
CheckedListBox by simply doing- CheckedListBox
CheckedListBox1.Items.Add("A1");
I put "Tricky" in the title because I'm aware that it will be hard to understand precisely what I want but I'll try to be clear.
I have a textBox with an event for TextChange which allow me to create the number of texboxes the user want (we will call it tChange).
Here is a part of the code for this event :
int tester;
bool flag = false;
if (!Int32.TryParse(tChange.Text, out tester))
{
flag = false;
return;
}
else
{
num = Convert.ToInt16(tChange.Text);
flag = true;
}
if (flag == true)
{
if (num >= 1)
{
for (int i = 0; i < num; i++)
{
this.Size = new Size(590, 225 + 105 * i);
textBoxesQ[i] = new TextBox();
this.Controls.Add(textBoxesQ[i]);
textBoxesQ[i].Size = new Size(45, 20);
textBoxesQ[i].Location = new Point(25, 100 + 100 * i - 1);
}
}
}
So the user enter the value and everything is OK. If he wants to change the number in the tChange, no problem too! The form is resize and the TextBoxes are created. However if he does this (change the value of tChange), everything goes wrong! Errors like
Index out of range
or I can't get the values from the TextBoxes etc..
I started thinking that the TexBoxes were created in front of the previous ones and the error came from this, so I tried to put the new ones to front, bring the old ones to front but none worked..
textBoxesQ[i].BringToFront();
textBoxesQ[i].SendToBack();
I also tried to delete the old ones before creating the new but I think that my code was wacky and it didn't work at all.
textBoxesQ[i].Dispose();
EDIT : As #Dr. Stitch said, It may come from not reinitializing the TextBoxes each time the text in tChange is changed. Now I just need to figure out how to make it happen.
You need to do three things when the number changes:
Remove any existing textboxes
Create a new array with the new size, and save a reference to that new array into your field (textBoxesQ)
Initialize the array
So something like:
if (textBoxesQ != null)
{
foreach (var textBox in textBoxesQ)
{
Controls.Remove(textBox);
}
}
textBoxesQ = new TextBox[size];
for (int i = 0; i < size; i++)
{
var textBox = new TextBox
{
Size = new Size(45, 20);
Location = new Point(25, 100 + 100 * i - 1);
};
Controls.Add(textBox);
textBoxesQ[i] = textBox;
}
I have been reading for a bit and found some things close, but not anything works in my case. The user has a settings file that they use and I read it into the Windows form. One tab has 2 standard columns but then there can be any number more after those two which have different labels and listbox names that are based on the label (i.e. if the label is "portland" the corresponding listbox is "lstportland" but these names WILL vary). There are created in the is part of the settings file import method, on the fly:
for (int i = 3; i < (lastColumn); i++)
{
//creates new list box and names it the column name with a "lst" infront of it
var cellVal = squidSheet.Cells[1, i].Value;
string convertString = cellVal.ToString();
string listBoxName = "lst" + convertString;
int lbLocation = new int();
/*where to place the next label/listbox on the sheet based on a placement point if its the first one
*it is placed in a specific spot, then each subsequent one is placed equidistant from the last.*/
if (i==3)
{ lbLocation = 382; }
else
{ lbLocation = 382 + (115*(i-3)); }
//create the properties for the new listbox and label in its proper place on the "Run Tab"
ListBox listBox1 = new ListBox();
Label label1 = new Label();
listBox1.Name = listBoxName;
listBox1.Height = 316;
listBox1.Width = 94;
listBox1.Location = new Point(lbLocation, 30);
label1.Location = new Point(lbLocation, 14);
label1.Text = convertString;
label1.Name = "lbl" + convertString;
label1.Font = new Font("Microsoft Sans Serif", 8, FontStyle.Regular);
//add the new listbox and label to the Form
tabPage4.Controls.Add(listBox1);
tabPage4.Controls.Add(label1);
//fill the new list box
string colIdString = TestCase((i-1).ToString());
fillListBox(listBox1, lastRowRunList, squidSheet, colIdString);
}
In a Later method, I need to read the items of each listbox created on the fly, into its own array or somehow access the items in the listbox itself. I have sketched the following but it doesn't work. Any ideas?
for (int l = 2; l < (listBoxNames.Count); l++)
{
string variableNameString = labelText[l].ToString();
string variableNames = "#" + variableNameString + "#";
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
string variableValues = listboxTest.Items[(l-1)].ToString();
readText = readText.Replace(variableNames, variableValues);
}
The control isn't being found because you are searching the Form's Controls() collection, instead of its actual container, tabPage4.
Change:
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
To:
ListBox listboxTest = tabPage4.Controls[("lst" + variableNameString)] as ListBox;
Or search for the control as in the link provided by drzounds in the comments.
I have a list that is created from a LINQ to XML query. The list can contain 1, 2, 3 or 4 values. I have four text boxes on the form that should be populated based on the values in the List, but I can't figure out how to do this because the number of elements in the list will vary. Would it be better to dynamically create the textboxes based on the number of values in the list? How could I go about this?
It seems like this would be a fairly common task, but I have not been able to find a solution. Any help would be greatly appreciated.
Creating dynamically, or just populating an existing 4, it doesn't matter. Choose which one is best for your UI requirements. (maybe even a DGV as has been suggested already)
First you need something to contain the controls, lets say you have a panel called MyPanel which will hold only these textboxes and nothing else...
Here's the load dynamically approach:
MyPanel.Controls.Clear();
int count = 1;
foreach(var item in listOfValues)
{
TextBox tb = new TextBox();
tb.Name = "MyTextbox" + i;
tb.Text = item.ToString();//or whatever property you have for the value
tb.Location = new Point(0, 0 + (25 * (i - 1)));
MyPanel.Controls.Add(tb);
}
Here is the fill existing approach, assuming you have 4 TextBoxes called "TextBox1" for example:
int count = 1;
foreach(var item in listOfValues)
{
TextBox tb = MyPanel.Controls.Find("TextBox" + i) as TextBox;
tb.Text = item.ToString();//or whatever property you have for the value
}
NOTE: You need to be sure that listOfItems does not contain more items than you have textboxes for, otherwise you will get an exception
lets say you have a List
List<int> testList = new List<int>(){1,2,3};
foreach(int i in testList)
{
TextBox test = new TextBox();
test1.Name = "textBox"+i;
youcOntrl.Controls.Add(test1);
}
You can also give them their location and size etc.
Sounds like you want to create a foreach loop and iterate round the linq query creating a new text box on each one and adding it to your form. It'd help to see what you've got so far. I've put an example below using a list instead of a linq query but what comes after it is the same
private void Form1_Load(object sender, EventArgs e)
{
var newList= new List<string> {"box1", "box2", "box3"};
foreach (var boxName in newList)
{
TextBox newTextBox = new TextBox();
newTextBox.Text = boxName;
this.Controls.Add(newTextBox);
}
}
You can create 4 text boxes in the forms designer and set their Visible property to be false as default (from the properties pane).
Then, you can switch on the count property of your list as follows:
switch (els.Count)
{
case 1:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
break;
case 2:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
break;
case 3:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
textBox3.Text = els[3].Value;
textBox3.Visible = true;
break;
case 4:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
textBox3.Text = els[3].Value;
textBox3.Visible = true;
textBox4.Text = els[4].Value;
textBox4.Visible = true;
break;
default:
break;
}
If your list is IEnumerable, then you must first call the ToList() method on it to get a List<XElement> as IEnumerable type does not have a Count property.
If it is four or less then you don't have to create dynamically the textboxes. You could probably disable the textbox(es) that could not be populated. And specially if you name your textbox sequentially like TextBox1, TextBox2 etc then you could probably code like:
for (int i = 1; i <= 4; i++)
{
if (i <= list.Count)
{
this.Controls["TextBox"+i.ToString()].Text = list[i-1];
this.Controls["TextBox"+i.ToString()].Enabled = True;
}
else
{
this.Controls["TextBox"+i.ToString()].Enabled = False;
}
}
So, if you have 2 Items in your List for example then List.Count is 2 and therefore Textbox1 and 2 would be populated and TextBox3 and 4 will be disabled.
I need to dynamically create radio buttons based on dynamic list. Scenario is like I have list of files shown as Radio button in WinForm. A user clicks on radio button to select file and move forward.
I tried doing following as an example
for (int i = 0; i < 10; i++)
{
ii = new RadioButton();
ii.Text = i.ToString();
ii.Location = new Point(20, tt);
tt = tt + 20;
panel1.Controls.Add(ii);
}
The problem is how would I check which value got selected by user?
A simple way to do it is by using the RadioButtons CheckChanged event to set a variable that specifies the file that they have chosen by using the RadioButtons text or Tag property which you could set to be the file itself?
e.g.
private File f = null;
for (int i = 0; i < 10; i++)
{
ii = new RadioButton();
ii.Text = i.ToString();
ii.Location = new Point(20, tt);
ii.Tag = fileArray[i]; // Assuming you have your files in an array or similar
ii.CheckedChanged += new System.EventHandler(this.Radio_CheckedChanged);
tt = tt + 20;
panel1.Controls.Add(ii);
}
private void Radio_CheckedChanged(object sender, EventArgs e)
{
RadioButton r = (RadioButton)sender;
f = (File)r.Tag;
}
It's certainly not the most elegant way but it would work.