WinForm, Dynamic Label delete (Beginner) - c#

I made 10 Labels dynamically.
Now, I'd like to delete them with the same way (dynamically).
What do I have to do ?
Thanks..
for( int i = 1 ; i < 11 ; i++ )
{
var myLabel = new System.Windows.Forms.Label();
myLabel.Text = "dynaLabel_" + i.ToString();
myLabel.Location = new System.Drawing.Point(200, i * 23);
Controls.Add(myLabel);
Application.DoEvents();
Thread.Sleep(199);
}

Just a simple for loop in which you should find out label, remove it from Controls and release allocated resources:
// let's use regular expression to validate name;
// String.StartsWith is also a good choice
using System.Text.RegularExpressions;
...
// while removing, loop backward
for (int i = Controls.Count - 1; i >= 0; --i) {
Label label = Controls[i] as Label;
// Control is Label with specific name
if ((label != null) && Regex.IsMatch(label.Text, "^dynaLabel_[0-9]+$")) {
Controls.RemoveAt(i);
// do not forget to release resources allocated (here is HWND - window handle)
label.Dispose();
}
}

So is this your homework?
using System.Linq;
...
foreach(Control c in Controls.OfType<Label>().ToList())
{
//check if correct label if you need to
Controls.Remove(c);
}

You could use Controls and LINQ Where to do the job:
var labels = Controls.Cast<Control>()
.Where(c => c is Label && c.Text.StartsWith("dynaLabel_"));
foreach (var label in labels){
Controls.Remove(label);
label.Dispose();
}
Since you create the labels as Label and having the Text starting with value of dynaLabel_, your LINQ should also find those specific labels. Thus, you use both c is Label and StartsWith("dynaLabel_") there.

Related

How to set a variable in a labelname

in my project i have 8 dynamic Textboxes and 8 dynamic Labels, which were created in c#.
Now i need to read the text in it and insert it in a db.
My current script looks like
Label labelname1 = this.Controls.Find("label1", false).FirstOrDefault() as Label;
Label labelname2 = this.Controls.Find("label2", false).FirstOrDefault() as Label;
Label labelname3 = this.Controls.Find("label3", false).FirstOrDefault() as Label;
.....
Is it possible, to create a while loop with a variable like:
int i = 1;
while (a < 9)
{
label Labelname+i = this.Controls.Find("label+i" + a, false).FirstOrDefault() as Label;
i++;
}
When I take the "labelname+i" it's not possible, because it isn't a string.
Thank you
Extract method then
private T FindControl<T>(string name) where T : Control {
return this
.Controls
.Find(name, false)
.OfType<T>()
.FirstOrDefault();
}
and use it in a loop (it seems you want for one):
for (int i = 1; i < 9; ++i) {
Label myLabel = FindControl<Label>($"label{i}");
if (myLabel != null) {
//TODO: Put relevant code here
}
}
Same loop if you want to enumerate TextBoxes:
// textBox1..textBox8
for (int i = 1; i < 9; ++i) {
TextBox myTextBox = FindControl<TextBox>($"textBox{i}");
if (myTextBox != null) {
//TODO: Put relevant code here
}
}
You can create a List of Labels and try like:
List<Label> labels = new List<Labels>();
for (int i=1;i<9;i++)
{
Label lbl = this.Controls.Find("label"+i.ToString(), false).FirstOrDefault() as Label;
labels.Add(lbl);
}
And if you want to access i Label you simply do:
labels[i] ...

How to assign text to a Label with the Label ID being assigned by a string?

Target:
To write in the label text, but the label ID is assigned by a string.
Problem:
It doesn't work, no errors given. I looked in most places for an answer but nothing helped!
My Code:
string asdfj = treeView2.SelectedNode.Text;
string adqien = System.IO.Path.Combine(dir7, asdfj);
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
h1a.Text = "100";
for (int o = 2; o > 6; o++)
{
//This is the label name e.g "h2a',h3a" etc
string tempc = string.Format("h" + o.ToString() + "a");
foreach (Control ctr in this.Controls)
{
if (ctr is Label)
{
if (ctr.Name == tempc)
{
ctr.Text = tnsop[o];
}
}
}
}
I also consulted this post:
Use string variable content as label ID to update label.Text, I get error - 'string' does not contain a definition for 'Text'
You can do it simply like:
this.Controls.Find(labelname).Text = Value;
or
this.Controls.OfType<Label>().FirstOrDefault(x => x.Name == labelName).Text = Value;
The for loop
First of all, this is wrong for (int o = 2; o > 6; o++).
It starts at o = 2, then checks if o > 6, which is false, because o = 2, and then skips the loop.
I guess you wanted to write: for (int o = 2; o < 6; o++). I am not sure about that, fix it as appropiate.
Addendum: This would have been easily discovored by debugging and stepping. You can start by adding a break point on your code (in Visual Studio you can place your cursor on the desired line and press F9 - by default) and then run in the debugger. When the a line with the break point is reached, the debbuger stops the execution and let you inspect the values of the variables, the call stack, etc. You can then step with F10 or F11 (if you want to inside a method call) and see how the code evolves. You would notice it does not enter the for loop.
Finding the labels
If finding the label still does not work, I would guess the problem is that the labels are not directly on the form or that they do not have the given name.
You can use this.Controls.Find(name, searchAllChildren) to get the labels you need.
That is:
string labelName = string.Format("h" + o.ToString() + "a");
Control[] control = this.Controls.Find(labelName, true);
Note: Yes, I can figure out it is the name of the label by how you use it. Using a comment to tell me saves some time... however, please use better variable names. You won't need a comment to tell me this is the name of the label if the variable name says so.
You still need to check it for the label:
string labelName = string.Format("h" + o.ToString() + "a");
Control[] controls = this.Controls.Find(labelName, true);
foreach (Control control in controls)
{
if (control is Label) // if (control.GetType() == typeof(Label))
{
// ...
}
}
Building a Dictionary
However, I would advice against doing this every time. Instead, I suggest to build a dictionary:
Dictionary<string, Label> labels;
// ...
labels = new Dictionary<string, Label>();
for(int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
Label label = GetLabel(labelName);
labels.Add(labelName, label);
}
// ...
private Label GetLabel(string labelName)
{
Control[] controls = this.Controls.Find(labelName, true);
foreach (Control control in controls)
{
if (control is Label) // if (control.GetType() == typeof(Label))
{
return control as Label;
}
}
return null;
}
Note: I suggest to make the dictionary a field and initialize it only once during the form load.
This separates the responsability of finding the labels from reading the file (which is external to the program). Allowing you to test if it can find the right controls without the need of a file.
It will also make the case where the Label is not found visible (we just added a null to the dictionary).
And then use it:
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
label = labels[labelName];
label.Text = tnsop[o];
}
The code above should throw NullReferenceException if the label was not found while building the dictionary.
Simplify
I guess we can do better. The designer will create fields for your labels, you can just add them to the dictionary:
Dictionary<string, Label> labels;
// ...
labels = new Dictionary<string, Label>();
labels["h2a"] = h2a;
labels["h3a"] = h3a;
labels["h4a"] = h4a;
labels["h5a"] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
label = labels[labelName];
label.Text = tnsop[o];
}
Note: There are plenty of opportunities for more modern syntax, including collection initialization and the var keyword.
Addendum: I am unrolling the loop in the above code, this is ok for maintainability if the number of iterations small, in fact, it is a common optimization. You could, in theory do it for the other loop too.
PS. An array will do
I noticed, after finishing writing, that the code only needs to look up by an int o.
We can rework to use int for dictionary keys:
Dictionary<int, Label> labels;
// ...
labels = new Dictionary<int, Label>();
labels[2] = h2a;
labels[3] = h3a;
labels[4] = h4a;
labels[5] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
label = labels[o];
label.Text = tnsop[o];
}
Now we have less concatenations, and a simpler code.
We could, in fact, be using an array:
Label[] labels;
// ...
labels = new Label[4];
labels[0] = h2a;
labels[1] = h3a;
labels[2] = h4a;
labels[3] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
label = labels[o - 2];
label.Text = tnsop[o];
}
Notice I did offset the indexes to be able to use the array from index 0.

Change text in multiple textboxes?

How would I go about making a for loop that changes the text in more than 1 textbox?
for (int i; i < 5; i++)
{
textbox(i).text = "something"
}
But I don't know how to get the I to represent the number after the textbox, does anyone know how to?
Store the textboxes in an Array and then loop over the array
for (int i; i < 5; i++)
{
textboxArray[i].text = "something"
}
You could use Controls.Find:
var txts = this.Controls.Find("textbox" + i, true); // true for recursive search
foreach(TextBox txt in txts)
txt.Text = "something";
or - if the TextBoxes are in the same container control(like the Form or a Panel)- with LINQ:
var txts = this.Controls.OfType<TextBox>().Where(txt => txt.Name == "textbox" + i);
foreach(TextBox txt in txts)
txt.Text = "something";
Actually you don't need the loop variable, you could also use String.StartsWith to get all:
var txts = this.Controls.OfType<TextBox>().Where(txt => txt.Name.StartsWith("textbox"));
foreach(TextBox txt in txts)
txt.Text = "something";
if you dont want to alter every textbox on your form just simply add them to a List:
List<TextBox> TextBoxes = new List<TextBox>();
TextBoxes.Add(This.TextBox1);
TextBoxes.Add(This.TextBox3):
then as others have suggested you could either linq or regular foreach the textboxes in the list
TextBoxes.Foreach(Textbox => TextBox.Text = "something");
or
foreach (TextBox r in TextBoxes)
{
r.Text = "something;
}

Clearing MOST labels on form, NOT all

I need to clear 32 labels on my windows form application, there are other labels present but I do NOT want to clear these. Is there a more efficient and less coded way to do this? My code for this at the moment is as follows using a method: (snippet)
private void ClearFields()
{
label50.Text = string.Empty;
label51.Text = string.Empty;
label52.Text = string.Empty;
label53.Text = string.Empty;
label54.Text = string.Empty;
label55.Text = string.Empty;
// Down to label82
}
I have researched but it's always clearing ALL labels/textboxes.
You could add an object to the Tag of the Label you want to clear.
Label label50 = new Label();
bool deleteMe = true;
label50.Tag = deleteMe;
Then just iterate over your labels and clear all where the Tag is true:
foreach(Label lbl in myLabels)
{
if(lbl.Tag != null && lbl.Tag is bool && (bool)lbl.Tag == true)
{
lbl.Text = String.Empty;
}
}
Try following line:
foreach (Label _label in this.Controls.OfType<Label>().Where(a => a.Name != "Lable32").Select(a => a).ToArray())
_label.Text = string.Empty;
Add non removal lable in where condition if there are many. Here except lable32 all lable text will set to empty.
I would recomend you to place all the labels that need to be cleared in some kind of cointainer. That way you can do something of the sort:
foreach (var child in container.Children)
{
if (child is Label)
{
((Label)child).Text=String.Empty;
}
}
I am not very familiar with WinForms, but I think there are containers there.
Set the Tag property of the labels you do not want cleared to the string "DoNotClear" (using the Property Window or code) then use the following LINQ code:
foreach (var label in Controls.OfType<Label>().Where(l => l.Tag != "DoNotClear"))
label.Text = string.Empty;
Solution : you can use Controls.Find() method to find the controls from id label50 to label82 and assign String.Empty for each identified Label.
Try This:
private void button1_Click(object sender, EventArgs e)
{
for(int i=50;i<83;i++)
{
this.Controls.Find("label" + i,true)[0].Text = String.Empty;
}
}
If all your labels have names like label + id
var labelsToClear = from l in Controls.OfType<Label>()
let id = Int32.Parse(l.Name.Replace("label", ""))
where id >= 50 && id <= 82
select l;
foreach(var label in labelsToClear)
label.Text = String.Empty;
If labels can have different names, then you can filter out labels which match label + id pattern:
Controls.OfType<Label>().Where(l => Regex.IsMatch(l.Name, #"^(?:label)\d+$"))

Check if TextBox is created, then assign it's value

I'm trying to make a small app, for make my job easier creating definitions (new web forms aspx) via WinForms C#.
Now I have this form, where I tell the app how many textboxes I want to create.
After their creation, I want to assign to a string the textboxes values that I wrote.
private void CreateControls()
{
for (int index = 0; index < NumberOfRows; index++)
{
TextBox textBox = new TextBox();
textBox.Name = "TextBox" + (index + 1).ToString();
textBox.Size = new Size(120, 20);
textBox.Location = new Point(X, Y + 26);
ComboBox comboBox = new ComboBox();
comboBox.Name = "ComboBox" + (index + 1).ToString();
comboBox.Size = new Size(75, 20);
comboBox.Location = new Point(141, Y + 26);
comboBox.DataSource = Enum.GetNames(typeof(DataTypes));
Y += 26;
this.Controls.Add(textBox);
this.Controls.Add(comboBox);
}
}
Now, I don't know how to check if the textboxes are created, and then take their values.
Could anyone refer me something? Thanks :)!
You'll need to, on Page_Load, find those controls and grab their values. Since you gave them meaningful names when you created them, this should do the trick:
for (int index = 0; index < NumberOfRows; index++)
{
TextBox textBox = this.FindControl(
string.Format("TextBox{0}", index)) as TextBox;
if (textBox == null) { continue; } // this means it wasn't found
var text = textBox.Text;
// work with the text
}
However, if the ComboBox class you're using isn't a third-party one and it's not an ASP.NET application, the code would work for a Windows Forms application as well with a minor modification:
for (int index = 0; index < NumberOfRows; index++)
{
// you have to use the Find method of the ControlCollection
TextBox textBox = this.Controls.Find(
string.Format("TextBox{0}", index)) as TextBox;
if (textBox == null) { continue; } // this means it wasn't found
var text = textBox.Text;
// work with the text
}
I tend to agree with the community that it's probably a Windows Forms application because you can't set the Location of a standard ASP.NET control. However, if these are user controls, or third-party ones, that support those properties and render the appropriate CSS then we'd never know.
if(Page.FindControl("IDofControl") != null)
//exists
else
//does no exists

Categories

Resources