Creating C# winform simple dynamic controls - c#

private void CreateNewControl()
{
List<Control> list = new List<Control>();
TableLayoutPanel layout = new TableLayoutPanel();
layout.Dock = DockStyle.Fill;
this.Controls.Add(layout);
layout.ColumnCount = 3;
layout.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
for (int i = 0; i < 9; i++)
{
if (wantedType == DevExpress.XtraEditors.CheckEdit)
{
CheckBox chk = new CheckBox();
chk.Tag = i;
layout.Controls.Add(chk);
layout.AutoScroll = true;
}
if (wantedType == LabelControl)
{
Label chk = new Label();
chk.Tag = i;
layout.Controls.Add(chk);
layout.AutoScroll = true;
}
// I want to set the columnwidth of the layout so that when the labels are displayed they do not get clustered and look exactly like when displaying the checkboxes.How do I do it?

In general, what I do is:
Use the IDE in a 'prototype' project, to create a form with the controls in the positions that I want
Look at the source code created by the IDE (in the MyFormName.Designer.cs file) to see what source code is generated by the IDE to creat these controls
Create my own form in my real project, with hand-coded code that's based on what I learned from the prototype which I created using the IDE

// Loop through all the controls you want to add.
// Add a integer field that measures the highest width of each control like
int _iMaxWidth = 0;
for (int i=0; i < TotalControls.Count; ++i)
{
if ( control[i].Width > _iMaxWidth)
_iMaxWidth = control[i].Width
}
// Then you'll know what the width size of the column should be.
Col.Width = iMaxWidth + 2; // +2 to make things a little nicer.

Related

dynamically created labels overlap each other

I want to create labels that will follow one another. I have a grid name WordTemplateLayout to which I want to add the labels. I add them dynamically on the wpf window constructor after InitializeComponent() is called. Here is the method creating the labels:
private void CreateWordTemplate()
{
IList<char> template = CurrentGame.Template;
double widthPerBox = WordTemplateLayout.Width / template.Count;
//template.Count being a number, irrelevant to the question
for (int i = 0; i < template.Count; i++)
{
var templateVisual = new Label();
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
WordTemplateLayout.Children.Add(templateVisual);
}
}
the problem being, that what actually appends is that instead of the labels lining up one after the other, they overlap each other:
The aqua box is all the labels overlap each other
so what I am asking, is how can I make the labels line up (horizontally) instead of to overlap?
As others have pointed out, you're better off using a StackPanel, or learning how to use viewmodels and data binding. Having said that, to answer your direct question, here's how you'd do it programmatically.
**NOTE: Ignore the 5 that I'm passing in to the methods, and instead use your template.Count. This is was just for me to get it to work on my end.
public MainWindow()
{
InitializeComponent();
CreateGridLayout(5);
CreateWordTemplate(5);
}
// Define the Grid layout
// If you want the labels to follow one another horizontally, define columns.
// If you want them stacked vertically, instead define rows.
private void CreateGridLayout(int count)
{
for (int i = 0; i < count; i++)
{
WordTemplateLayout.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private void CreateWordTemplate(int count)
{
double widthPerBox = WordTemplateLayout.Width / 5;
for (int i = 0; i < 5; i++)
{
var templateVisual = new Label();
templateVisual.SetValue(Grid.ColumnProperty, i); // SET YOUR COLUMN HERE!
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
templateVisual.Content = templateVisual.Name;
WordTemplateLayout.Children.Add(templateVisual);
}
}
you need to use another layout so the new elements will get in normal order. try stackPanel.
you can use grid and give each new label Row=index.
you can give each new label margin, like newLabel.margin-top = index*50

C# display components based on name

Is it possible to set a components visible attribute based on its name?
I have 12 "master" components (comboboxes) if you want to call them that and based on the selection in these I want to display anywhere from 1 to 16 textboxes. These are named in numeric order such as combobox1_textbox_0, combobox1_textbox_1 and so on. What I would like to do ideally is take the index of the combobox and pass it as a parameter to a method that sets the textboxes visible attribute to visible/hidden depending on the index passed into the method.
Is this possible? in pseudocode or what you call it I would like it to work something like this:
private void methodToSetVisibleAttribute(int indexFromMainComboBox)
{
for(int i = 0; i < 15; i++)
{
if(i < index)
{
combobox1_textbox_+i.Visible = true;
}
else
{
combobox1_textbox_+i.Visible = false;
}
}
}
I could do panels or something for the choices but seeing as all the selections from the combobox will use the same textboxes but in different amounts it seems like alot of work to make a panel for every possible selection not to mention difficult to expand the program later on.
Assuming you are using Windows Forms and not WPF, you can use ControlCollection.Find() to find controls by name:
var textBox = this.Controls.Find(string.Format("combobox1_textbox_{0}", i), true).OfType<ComboBox>().FirstOrDefault();
if (textBox != null)
textBox.Visible = (i < index);
else
Debug.Assert(false, "textbox not found"); // Or throw an exception if you prefer.
I'll suggest an alternative to your approach, maybe not quite what you're looking for:
Place your combo boxes in a List<ComboBox> and you can access them by an index number.
List<ComboBox> myCombos = new List<ComboBox>();
for (int i = 0; i < 16; i++)
{
ComboBox cb = new ComboBox();
//do what ever you need to do here. Set its location, add items, etc.
Form1.Controls.Add(cb); //Alternatively add it to another container.
myCombos.Add(cb); //Now it's in a list.
}
Modify them like this:
for(int i = 0; i < 15; i++)
{
if(i < index)
{
myCombos[i].Visible = true;
}
else
{
myCombos[i].Visible = false;
}
}
Or even more succintly:
for(int i = 0; i < 15; i++)
{
myCombos[i].Visible = i < index;
}

How to write to a dynamical number of Textboxes?

I have a form (Windows Forms) with dynamically created textboxes:
TextBox[] tbxCantServ = new TextBox[1];
int i;
for (i = 0; i < tbxCantServ.Length; i++)
{
tbxCantServ[i] = new TextBox();
}
foreach (TextBox tbxActualCant in tbxCantServ)
{
tbxActualCant.Location = new Point(iHorizontal, iVertical);
tbxActualCant.Name = "tbx" + counter++;
tbxActualCant.Visible = true;
tbxActualCant.Width = 44;
tbxActualCant.MaxLength = 4;
this.Controls.Add(tbxActualCant);
}
Now I want to fill them with data, how could I do that?
If I created some textboxes dynamically with the names:
"tbxActualServ.Name = "txt" + counter;"
How can I write in them? How can I access to them?
For example, if I have created tbx1, tbx2 and tbx3, I would have a "for" that fills tbx1.Text with "1", tbx2.Text with "2", and tbx3.Text with "3".
something like
"for from i=0 to counter {
tbx[i] = i
}"
of like:
this.Controls.OfType<TextBox>().Where(r => r.Name == "tbx" + counter).¿¿Write??(r => r.Text = i).ToString();
Thanks!
You could do something like this:
this.Controls.OfType<TextBox>().ToList<TextBox>().ForEach(tb => tb.Text = "bla bla");
Evening,
Guessing from your tags that this is a web forms project.. Im going to have to make some other assumptions.
I am guessing that you are creating your text boxes in code, something like
TextBox tb1 = new TextBox();
form1.Controls.Add(tb1);
TextBox tb2 = new TextBox();
form1.Controls.Add(tb2);
If this is the case then I believe that you could do something like this:
for (int i = 0; i < 2; i++)
{
TextBox tb1 = page.findControl("tb" + i.ToString());
tb1.Text = "This is number " + i.ToString();
}
There is another alternative, you could keep a collection of the controls as you create them, you could then iterate over the collection.
To be honest, without more details about your code it will be difficult to give a full answer, I think that this answers what you are looking for, if not update your question with more details and more of the code (the code where you are dynamically creating the controls would be useful)
While it's possible to access controls by their names (the way you do it depends on the technology - are you using WinForms, WPF, Web Forms, ...?), using an array of controls is a much better solution. Here's some pseudo-C#:
MyControl[] controls = new MyControl[length];
for(int n = 0; n < controls.Length; n++)
{
controls[n] = new MyControl(...);
}
// ...
for(int n = 0; n < controls.Length; n++)
{
DoSomethingWith( controls[n] );
}

How to create multiple gridviews dynamically?

How to create multiple gridviews?
My code:
GridView gv = new GridView();
Panel PNl = new Panel();
for (int i = 0; i < DST.Tables.Count; i++)
{
gv.ID = DST.Tables[i].TableName;
gv.DataSource = DST.Tables[i];
gv.DataBind();
// form.Controls.Add(gv);
PNl.Controls.Add(gv);
}
//gv.Parent.Controls.Add(form);
form.Attributes["runat"] = "server";
form.Controls.Add(PNl);
this.Controls.Add(form);
However, my code is creating only one grid view.
Move the creation of the GridView inside the loop. This way you will create many grids and not just reuse one object. In practice you probably want to create a user control with the grid and use that since you will be able to specify different grid attributes in markup which is easier than specifying them in code.
int i=10;
GridView[] gc = new GridView[i];
for (int i = 0; i < 10; i++)
{
gc[i] = new GridView();
gc[i].ID = "gv" + i;
gc[i].CopyBaseAttributes(GridView1);
gc[i].AlternatingRowStyle.CopyFrom(GridView1.AlternatingRowStyle);
gc[i].BorderStyle = GridView1.BorderStyle;
gc[i].ControlStyle.CopyFrom(GridView1.ControlStyle);
gc[i].EditRowStyle.CopyFrom(GridView1.EditRowStyle);
gc[i].EmptyDataRowStyle.CopyFrom(GridView1.EmptyDataRowStyle);
gc[i].FooterStyle.CopyFrom(GridView1.FooterStyle);
gc[i].HeaderStyle.CopyFrom(GridView1.HeaderStyle);
gc[i].RowStyle.CopyFrom(GridView1.RowStyle);
gc[i].SelectedRowStyle.CopyFrom(GridView1.SelectedRowStyle);
gc[i].ShowHeaderWhenEmpty = true;
gc[i].RowDataBound += new GridViewRowEventHandler(Gv_RowDataBound);
//gc[i].EmptyDataText = "No ROWS Found in the particular month";
}
Have GridView1 in design page and set visible to false, so you can copy properties.

Dynamically creating variables in C#

I am trying to do something like this:
for (int i = 1; i < nCounter ; i++)
{
string dvName = "dv" + i.ToString();
System.Windows.Forms.DataGridView dvName = new DataGridView();
// other operations will go here..
}
As you can guess, what I am trying to do is at i == 1, create a DataGridView with name dv1, and at i == 2, create a DataGridView with name dv2, but I can't.
Visual studio squiggles saying "a local variable named dvName is already delared in this scope" I also tried the following:
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dv & i = new DataGridView();
// other operations will go here..
}
But VS squiggles again, I hope you understood what I am trying to accomplish. Can anyone suggest how can I do this?
What you really need is a Dictionary<int, DataGridView> grids. Populate it in your for loop (grids[i] = new DataGridView();) and then, later, use the required grid (grids[someCalculatedIndex])
Hope this helps.
try a data structure where you can hold your variables eg dict etc
System.Collections.Generic.Dictionary<string,System.Windows.Forms.DataGridView>
grids = new Dictionary<string,System.Windows.Forms.DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
grids.Add("dv" + i.ToString(), new DataGridView());
}
// to work on grid 1
DataGridView grid1 = grids["dv1"];
// so on
So your are trying to create the variable name dynamically? That's not possible. Why not use an Array or a List (or even a Dictionary)? Or do you want to just set the name of the control?
var list = new List<DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dvName = new DataGridView();
dvName.Name = "dv" + i.ToString();
list.Add(dvName);
// other operations will go here..
}
foreach (var dv in list)
{
...do something...
}
DataGridView secondDv = list.Single(dv=>dv.Name == "dv2");
secondDv.DoSomething()
Not clear want you want to do...

Categories

Resources