Background
I create a set of linklabel and label controls using a loop that uses data from a database as there content (Text).
Question
How do I then remove or change there visibility?
What I would Like to Happen?
On a button click event, I would like all of the link's and linklabel's text properties to be set to either null, or their visibility properties to be set as false.
Code
private void getInfoStationID()
{
//SQL Connection Stuff
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
Linklabel.Text = ds.Tables[0].Rows[i] ["code"].ToString();
Linklabel.Height = 15;
Linklabel.Width = 50;
Linklabel.AutoSize = true;
Linklabel.Location = new Point(10, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(Linklabel);
// Add an event handler to do something when the links are clicked.
Linklabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
Label label1 = new Label();
label1.Text = ds.Tables[0].Rows[i]["name"].ToString();
label1.Height = 15;
label1.Width = 70;
label1.Location = new Point(100, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label1);
Label label3 = new Label();
label3.Text = ds.Tables[0].Rows[i]["toc"].ToString();
label3.Height = 15;
label3.Width = 50;
label3.Location = new Point(240, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label3);
}
}
private void clearAllBtn_Click(object sender, EventArgs e)
{
//Would like this to clear all previously drawn labels and linklabels
}
Simply add the dynamic controls to a List so you have a quick reference to them:
// out at CLASS/FORM level:
private List<Control> MyControls = new List<Control>();
// ... some method ...
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
MyControls.Add(Linklabel);
// ... rest of your code ...
Label label1 = new Label();
MyControls.Add(label1);
// ... rest of your code ...
Label label3 = new Label();
MyControls.Add(label3);
// ... rest of your code ...
}
Now you can use that List from somewhere else:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Visible = false; // or something else
}
}
*Don't forget to dispose of those controls and empty the list if you decide to create a new set of dynamic controls. If you want to completely get rid of them:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Dispose();
}
MyControls.Clear();
}
You can loop through all controls on a certain tabpage. You could use a open generic function to make the code nice and clean. Like this:
private void HideControls<TControl>(Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
And use it like this:
private void button1_Click(object sender, EventArgs e)
{
this.HideControls<Label>(tabControl1.TabPages[0]);
this.HideControls<LinkLabel>(tabControl1.TabPages[0]);
}
You could even refactor this to a nice extension method:
public static class ControlExtensions
{
public static void HideControlsOfType<TControl>(this Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
}
and use like:
this.tabControl1.TabPages[0].HideControlsOfType<Label>();
Related
I have created a small kitchen display program that display food orders. So I created dynamically a panel that contains a table layout panel that contains a checked list box and a check all button . My problem is... I have a check all button in each table layout panel created dynamically and every time I click it, it checks all items in the last created CheckedListBox not the clicked one.
This is my code:
p = new Panel();
p.Size = new System.Drawing.Size(360, 500);
p.BorderStyle = BorderStyle.FixedSingle;
p.Name = "panel";
tpanel = new TableLayoutPanel();
tpanel.Name = "tablepanel";
clb = new CheckedListBox();
tpanel.Controls.Add(b1 = new Button() { Text = "CheckAll" }, 1, 4);
b1.Name = "b1";
b1.Click += new EventHandler(CheckAll_Click);
b1.AutoSize = true;
private void CheckAll_Click(object sender, EventArgs e)
{
var buttonClicked = (Button)sender;
var c = GetAll(this, typeof(CheckedListBox));
for (int i = 0; i < c.Count(); i++)
{
\\any help
}
}
public IEnumerable<Control> GetAll(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type)).Concat(controls).Where(c =>
c.GetType() == type);
}
First I will describe the struct
Order = TableLayoutPanel
TableLayoutPanel has 1 CheckAll Button and CheckListBox
And you want when you click to CheckAll Button it will checks exactly all items in current TableLayoutPanel.
So try this code
class XForm : Form {
// create Dictionary to store Button and CheckListBox
IDictionary<Button, CheckListBox> map = new Dictionary<Button, CheckListBox> ();
// when you create new order (new TableLayoutPanel)
// just add map Button and CheckListBox to map
private void CreateOrder () {
var panel = new Panel ();
panel.Size = new System.Drawing.Size (360, 500);
panel.BorderStyle = BorderStyle.FixedSingle;
panel.Name = "panel";
var table = new TableLayoutPanel ();
var checklistBox = new CheckedListBox ();
var button = new Button () { Text = "CheckAll" };
table.Controls.Add (button, 1, 4);
button.Name = "b1";
button.Click += new EventHandler (CheckAll_Click);
button.AutoSize = true;
map[button] = checklistBox;
}
// and on event handle
private void CheckAll_Click (object sender, EventArgs e) {
var buttonClicked = (Button) sender;
var c = map[buttonClicked];
if (c == null) return;
for (int i = 0; i < c.Items.Count; i++)
{
c.SetItemChecked(i, true);
}
}
}
And dont for get remove it from map when remove the order.
Hope it helps
I made dynamic textboxes and keep it List
private void ConvertButton_Click(object sender, EventArgs e)
{
List<TextBox> textBoxes = new List<TextBox>();
foreach (Control item in this.Controls)
{
if (item is TextBox)
{
TextBox txt = item as TextBox;
textBoxes.Add(txt);
}
}
}
I get all of textboxes value but i have a problem. For examples; if user add 3 label like (A,B,C) and add Textboxes for them like (labelA has 2,labelB has 3,labelC has 1) and textboxes get value like array (textboxes[0] has value).The problem is i dont know which label has which value.
I added Textbox just like this:
private void addNewTextbox(object sender, EventArgs e)
{
Button button = (Button)sender;
List<TextBox> textBoxes = button.Tag as List<TextBox>;
if (textBoxes == null)
button.Tag = textBoxes = new List<TextBox>();
TextBox textBox = new TextBox();
textBoxes.Add(textBox);
textBox.Location = new Point(90 * textBoxes.Count, button.Top);
textBox.Size = new Size(50, 50);
this.Controls.Add(textBox);
}
I try to show screen for example;
LabelA-->Textbox1 , Textbox2
</br>
labelB -->Textbox3
</br>
LabelC --> Textbox4 , Textbox5 , TextBox6
Every control that is added has a Name property. Use this property to link the different controls together. For example (and you should come up with your own naming convention), you could do this:
LabelA --> TextboxA1, TextboxA2
LabelB --> TextboxB1
LabelC --> TextboxC1, TextboxC2, TextboxC3
If you wish to have a more complete (i.e. complex) solution, you could:
Create your own control that inherits from TextBox
Add a property for the name of the associated Label control
Set this property when a new control is instantiated
Label[] labelArray = new Label[10];
for (int i = 0; i < labelNumber; i++)
{
labelArray[i] = new Label();
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
}
i did label-created just like this.labelnumber is how many label user wants.#interceptwind
I am trying very hard to understand your question, I guess you are trying to link the user-created textboxes to specific labels? Forgive me if I am completely wrong. How about structure your code to something like this:
Note: Edited with OP's new code
Dictionary<Int, List<TextBox>> label_Textboxes_Dict = new Dictionary<Int, List<TextBox>>();
List<Label> labelArray = new List<Label>(); //I suggest use list as you don't know the array size beforehand
void addLabel(int labelNumber)
{
int currentLabelArrayCount = labelArray.count; //So that users can add multiple times
for (int i = currentLabelArrayCount; i < currentLabelArrayCount +labelNumber; i++)
{
labelArray.Add(new Label());
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
label_Textboxes_Dict.Add(i, new List<TextBox>());
}
}
void addTextBoxForLabel(int labelNum)
{
TextBox t1 = new TextBox();
TextBox t2 = new TextBox();
//etc...
if (label_Textboxes_Dict.ContainsKey(labelNum))
{
label_Textboxes_Dict[labelNum].Add(t1);
label_Textboxes_Dict[labelNum].Add(t2);
}
}
void doSomethingForAllTextboxesOfLabel(int labelNum)
{
List<TextBox> listOfTextBoxes;
if(label_Textboxes_Dict.TryGetValue(labelNum, out listOfTextBoxes))
{
foreach(TextBox tb in listOfTextBoxes)
{
//do your stuff
}
}
}
I have a problem with a Dynamic Textbox event. I got other dynamic textbox with their textchanged events, the others work good, but this one never get into the event, the property AutoPostBack = true, EnabledViewState too, EnabledViewTheming too, and it's into an UpdatePanel and I create a Dynamic Trigger.
This is my code:
TextBox DescUnit = new TextBox();
DescUnit.ID = "DescUnit_txt" + (No).ToString();
DescUnit.Text = "0.0";
DescUnit.TextChanged += new EventHandler(DescUnit_TextChanged);
DescUnit.AutoPostBack = true;
DescUnit.EnableViewState = true;
DescUnit.EnableTheming = true;
Trgr = new PostBackTrigger();
Trgr.ControlID = DescUnit.ID;
UpdatePanel1.Triggers.Add(Trgr);
Table.Rows[i - 1].Cells[3].Controls.Add(DescUnit);
And this is the code of my Event
protected void DescUnit_TextChanged(object sender, EventArgs e)
{
Descuento_Row.Visible = true;
int i = 1;
foreach (HtmlTableRow Row in Tab.Rows)
{
if (Row.ID != null && String.Compare(Row.ID.Substring(0, 6), "TRDet_") == 0)
{
Detalle = (HtmlTable)(Row.Cells[0].Controls[0]);
if (sender.Equals(Detalle.Rows[1].Cells[3].Controls[0]))
{
TextBox Cantidad = new TextBox();
Clonar(Tab.Rows[i].Cells[1].Controls[0], Cantidad);
TextBox Precio = new TextBox();
Clonar(Tab.Rows[i].Cells[4].Controls[0], Precio);
TextBox DescUnit = new TextBox();
Clonar(Detalle.Rows[1].Cells[3].Controls[0], DescUnit);
TextBox ImpDesc = new TextBox();
Clonar(Detalle.Rows[2].Cells[4].Controls[0], ImpDesc);
ImpDesc_txt.Text = ((Convert.ToDouble(ImpDesc_txt.Text) - Convert.ToDouble(ImpDesc.Text)) + (Convert.ToDouble((Convert.ToDouble(DescUnit.Text) / 100)) * (Convert.ToDouble(Precio.Text) * Convert.ToInt32(Cantidad.Text)))).ToString();
ImpDesc.Text = (Convert.ToDouble((Convert.ToDouble(DescUnit.Text) / 100)) * (Convert.ToDouble(Precio.Text) * Convert.ToInt32(Cantidad.Text))).ToString();
Detalle.Rows[2].Cells[4].Controls.Clear();
Detalle.Rows[2].Cells[4].Controls.Add(ImpDesc);
}
i = i + 2;
}
}
}
But never get into it. Can anyone help me?
When ever we are creating controls in ASP.Net the controls can be create on form load or after it. But if you want events of the controls. you should initialize it in onInit Method. Then It will work properly.
If suppose I want to create dynamic textbox and its event. and want to add it in panel
Please refer following code.
protected override void OnInit(EventArgs e)
{
TextBox t = new TextBox();
t.ID = "t01";
t.TextChanged += t_TextChanged;
t.AutoPostBack = true;
Panel1.Controls.Add(t);
}
protected void t_TextChanged(object sender, EventArgs e)
{
}
Also please be sure that ID of the control is properly. Must interger,underscore and alphanumeric. ex t001, t_1 etc
But should not space.
I need to dynamically create buttons with labels under them in a flowLayoutPanel when i drop a file onto the form. But how do I set the label position to be under the button since the FLP is arranging the controls by itself.. ?
What I've tried:
void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach (string s in fileList)
{
Button button = new Button();
button.Click += new EventHandler(this.button_Click);
fl_panel.Controls.Add(button);
Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
Bitmap bmp = icon.ToBitmap();
button.BackgroundImage = bmp;
button.Width = 60;
button.Height = 75;
button.FlatStyle = FlatStyle.Flat;
button.BackgroundImageLayout = ImageLayout.Stretch;
int space = 5;
int Yy = button.Location.Y;
int Xx = button.Location.X;
Label label = new Label();
label.Location = new Point(Yy + space, Xx);
//label.Margin.Top = button.Margin.Bottom;
fl_panel.Controls.Add(label);
}
}
The best idea I know of is to implement a custom control that contains both a button and a label that are arranged correctly. Then add the custom control to the FlowLayoutPanel.
public class CustomControl:Control
{
private Button _button;
private Label _label;
public CustomControl(Button button, Label label)
{
_button = button;
_label = label;
Height = button.Height + label.Height;
Width = Math.Max(button.Width, label.Width);
Controls.Add(_button);
_button.Location = new Point(0,0);
Controls.Add(_label);
_label.Location = new Point(0, button.Height);
}
}
You can then add to it like this:
for (int i = 0; i < 10; i++)
{
CustomControl c = new CustomControl(new Button {Text = "Button!"}, new Label {Text = "Label!"});
fl_panel.Controls.Add(c);
}
EDIT:
If you want to listen to button events, try this:
for (int i = 0; i < 10; i++)
{
var button = new Button {Text = "Button " + i};
CustomControl c = new CustomControl(button, new Label {Text = "Label!"});
button.Click += buttonClicked;
fl_panel.Controls.Add(c);
}
...
private void buttonClicked(object sender, EventArgs e)
{
MessageBox.Show(((Button) sender).Text);
}
What am doing here is; making a UI to update values visually, will add more support for other types too. Possibly all types.
updateIcons this function is called everytime the controller is loaded, and has new values,names everytime.
countControls to keep track of controllers, so if can update values on clicks.
myP is the object that holds the values taken at runtime, user shuffles values by pressing tab from another screen
created radiobuttons groupboxes to allow radiobutton group to be managed.
properties all belong to one object. each property has few possible values like in my example, the enums.
now am kinda lost, not sure how to best do this, as now my rb_CheckedChanged is returning some kind of mess.
How do i do this the right way ? all together, i feel its somewhat the right approach At least.
I thought of making a dictionary of ? to use it at the checked event. not exactly sure how
private void updateIcons(List<Props> prop) {
countControls++;
locationY = 10;
int gbHeight;
foreach (var p in prop) {
radioButtonY = 10;
IType pType = p.Type;
if (pType is Enum) {
var myP = new MyProp(p, this);
GroupBox gb = new GroupBox();
gb.Location = new Point(nextLocationX,locationY);
nextLocationX += rbWidth+10;
gb.Name = "groupBox" + countControls;
gb.Text = "smthn";
var TypesArray = set here;
gbHeight = TypesArray.Length;
foreach (var type in TypesArray) {
getimagesPath(TypesArray);
RadioButton rb = new RadioButton();
rb.Appearance = Appearance.Button;
rb.Width = rbWidth;
rb.Height = rbHeight;
rb.Name = type.Name + countControls;
rb.Text = type.Name;
string path = imagePaths[type.Name];
Bitmap rbImage = new Bitmap(path);
rb.BackgroundImage = rbImage;
countControls++;
rb.Location = new Point(radioButtonX, radioButtonY);
if (myP.Value != null && type.Name.SafeEquals(myP.Value.ToString())) {
rb.Checked = true;
}
radioButtonY += rbHeight;
gb.Controls.Add(rb);
rb.CheckedChanged += rb_CheckedChanged;
}
gb.Height = rbHeight * gbHeight + 20;
gb.Width = rbWidth + 10;
Controls.Add(gb);
}
}
}
void rb_CheckedChanged(object sender, EventArgs e) {
RadioButton rb = (RadioButton)sender;
Control control = (Control)sender;
if (rb.Checked) {
MessageBox.Show("You have just checked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
var t = PropSeq;
}
else {
MessageBox.Show("you have just unchecked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
}
}
I think your code might be a little messed up and not the easiest to read. It looks plain invalid with not all closing braces present? Try the code below which will create two group boxes, each with five radio buttons. This should help you achieve what you are trying to do (full listing for a basic Form):
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CreateButton();
}
private void CreateButton()
{
// Add two group boxes
for (int groupCount = 1; groupCount < 3; groupCount++)
{
var groupBox = new GroupBox();
groupBox.Location = new Point(220 * (groupCount - 1), 10);
groupBox.Name = string.Format("groupBox{0}", groupCount);
groupBox.Text = string.Format("Group Box {0}", groupCount);
// Add some radio buttons to each
for (int buttonCount = 1; buttonCount < 6; buttonCount++)
{
var radioButton = new RadioButton();
radioButton.Width = 150;
radioButton.Location = new Point(10, 30 * buttonCount);
radioButton.Appearance = Appearance.Button;
radioButton.Name = string.Format("radioButton{0}", buttonCount);
radioButton.Text = string.Format("Dynamic Radio Button {0} - {1}", groupCount, buttonCount);
radioButton.CheckedChanged += radioButton_CheckedChanged;
// Add radio button to the group box
groupBox.Controls.Add(radioButton);
groupBox.Height += 20;
}
// Add group box to form
Controls.Add(groupBox);
}
}
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
// Get button and only show the selected (not now de-selected item)
var radioButton = (RadioButton)sender;
if (radioButton.Checked)
{
MessageBox.Show("You have just checked: " + radioButton.Text);
}
}
}
}