C# Call an object from concatenated text - c#

I was trying to call multiple labels with multiple names from a for loop, but the thing is that i dont want to use the "foreach" to loop trough all the controls.
I want to make a direct reference to it, for example :
for(ai = 2; ai < 11 ; ai ++)
{
this.Controls("label" + ai).Text = "SomeRandomText";
}
How can i do this?
I already tried to find this question on the net, but all i find are answers with "foreach" loops.
Thanks!!

Assuming that your labels are named "lable2" through "label10", then you can do it like this:
for(int ai = 2; ai < 11 ; ai++)
{
this.Controls["label" + ai].Text = "SomeRandomText";
}

Here is a solution that is not dependent on the control's name so you are free to change the name of the label at any point in time without breaking your code.
foreach (var control in this.Controls)
{
if (control is Label)
{
int index;
if (control.Tag != null && int.TryParse(control.Tag.ToString(), out index) && index >= 2 && index < 11)
{
((Label)control).Text = "SomeRandomText";
}
}
}
Then, all you need to do is assign a value between 2 and 11 to each control's Tag property that you want updated. You can set this property through code or set the property in the designer.
You are also free to change the values of the Tag property as you see fit. Just make sure the index checks in the code line up with the tag values you choose!

Related

assigning a position to each item in a list checking if one already exists

I have a list of "Boxes". there is a value called "position" against each box in the list.
When my list of boxes is built, some are given a position (int) . Position is a value used by my code to determine where each box fits on my page.
So, I have a list with 13 boxes, I have one box with position =13 and one with position 4. the rest are currently null.
There is another field called "order" against a box. What I need to do now is order everything that doesn't have a "position" value by the value in "order". (order is not nullable).
Easy so far. However, what I now need to do is loop each value returned and give them a position value. BUT I need to skip over the position values that are already taken (currently 4 and 13).
This is what I am doing:
var orderedBoxes = (from a in boxes
orderby a.Order
where a.Position == null
select a).ToList();
List<int> takenPositions = (from a in boxes
where a.Position != null
select a.Position).ToList();
foreach (var box in orderedBoxes)
{
if (takenPositions.Contains(i))
{
// i++
// box.Position =i;
}
//box.Position =i;
}
i thought this might be ok, but upon reflection, what if takenPositions Does contains i and the value after i++ is also in takenPositions?
I feel I need some form of loop here to test the result of i++ after each increment.
Can anyone offer any help please!!
It might be solved if you'd change
if (takenPositions.Contains(i))
in
while (takenPositions.Contains(i))
It automatically increments until it finds a free position.
Sometimes I use the good old for loop:
int j = 0;
for (int i = 1; i <= boxes.Count; i++)
{
if (takenPositions.Contains(i)) continue;
orderedBoxes[j++].Position = i;
}

How do I use a variable within a control name? (C#)

I want to compress this code into something much more simple, here's basically what code I've written, except I shortened it quite a lot.
if (chk1.Checked != true) lab1.Text = rng.Next(1, 7).ToString();
if (chk2.Checked != true) lab2.Text = rng.Next(1, 7).ToString();
Instead of many very similar lines, I want a few lines that does this in one go. I tried a 'for' loop, but I don't know how I can use the variable inside of a control name.
for (int x = 1; x == 7; x++)
{
if (chk{x}.Checked != true) lab{x}.Text = rng.Next(1, 7).ToString();
}
Obviously {x} doesn't work, but is there anything I can use to make this work?
It is best to create 2 equal sized arrays - one to hold the check boxes and one to hold the labels. Then your for loop will look like this:
for (int i = 0; i < 7; i++)
{
if (checkBoxes[i].Checked == false)
{
labels[i].Text = rng.Next(1, 7).ToString();
}
}
For some reason I am feeling this is a WinForms app, I may be wrong, but you need to be clearer in the future.
Each control will have a parent control. For example, all your controls may belong to the same Panel control. I will assume this is the case for this example. A Control has a Controls property which is a collection of child controls, these can be accessed be using the name of the control. So assuming you have your controls named the same as your variables above (named using either the designer, or the Name property), then you can do something like this...
for(int i = 1; i <= 7; i++)
{
Checkbox checkbox = MyParentPanel.Controls["chk" + i] as Checkbox;
Label label = MyParentPanel.Controls["lab" + i] as Label;
if(checkbox != null && label != null && !checkbox.Checked)
{
label.Text = rng.Next(1, 7).ToString();
}
}
Let me know if you don't understand any of that
a Dictionary would fit nicely in a 1:1 scenario where a CheckBox is "bound" to a Label. Here, the CheckBox acts as the Key and the Label acts as the value of the Dictionary, which can be strongly-typed to ensure you are handling the correct type of data at compile-time.
// Declare this at class level
private Dictionary<CheckBox, Label> myControls = new Dictionary<CheckBox, Label>();
// ...
// Dictionary initialization goes in the ctor
// unless you generate the controls at run-time.
// If you generate controls, place it after the generation itself
myControls.Add(chk1, lab1);
myControls.Add(chk2, lab2);
// and so on...
// ...
// When you want to cycle, do this:
foreach(var controlsPair in myControls) {
// controlsPair is KeyValuePair<CheckBox, Label>
if(controlsPair.Key.Checked) continue; // SEE (*) BELOW
controlsPair.Value.Text = rng.Next(1, 7).ToString();
}
(*): I always suggest to check for conditions trueness because I find the logic easier to understand when reading the code, but the behavior is exactly the same in the end.
Note: This code should work everywhere (WinForms, WPF, Silverlight, etc.)

Change text of a listview

I have a quick question about listView's and how check if a ListView (which contains null items) has a certain string?
Here is the code which add to sepcific items (under column 5 in the listView). It basically checks if that item appears in Google search or not. If it does, it'll write yes to that specific row, if not it'll leave it blank:
string google2 = http.get("https://www.google.com/search?q=" + textBox1.Text + "");
string[] embedid = getBetweenAll(vid, "type='text/html' href='http://www.youtube.com/watch?v=", "&feature=youtube_gdata'/>");
for (int i = 0; i < embedid.Length; i++)
{
if (google2.Contains(embedid[i]))
{
listView1.Items[i].SubItems.Add("Yes");
}
}
Now what I am trying to do is check if that certain column contains items that say Yes. If it does color them Green if not don't.
Here's the code for that:
if (i.SubItems[5].Text.Contains("Yes"))
{
labelContainsVideo.ForeColor = System.Drawing.Color.Green;
}
My issue is I keep getting an error that says InvalidArgument=Value of '5' is not valid for 'index'.
My hunch is that there are null items in column 5 which might be messing it up but I dont know.
Any idea on how to fix this?
Check the Item to see if the SubItem Collection has the correct Number of values.
i.e.
int threshold = 5;
foreach (ListViewItem item in listView1.Items)
{
if (item.SubItems.Count > threshold)
{
if (item.SubItems[5].Text.Contains("Yes"))
{
// Do your work here
}
}
}

Iterating over an array using index and assigning values depending on index

I was facing this problem earlier today, and since I could not find a satisfactory solution, I decided to change my class design, and have seperate properties such as Tag 1, Tag 2, Tag 3 etc.
My main problem is the fact that I need to bind a grid to an object that contains a list among other properties and I need to show each item in the list as a separate column which I am unable to do. Hence I am resorting to declaring variables separately. Original question is here...
Now, I'm facing one of the most common design problem that probably every programmer has at some point of time. Here is the code to demonstrate it,
for (int i = 0; i < tags.Length; ++i) // Length not known here.
{
if(i==0){
tag1 = tags[0];
}
else if(i == 1){
tag2 = tags[1];
}
else if(i == 2){
tag3 = tags[2];
}
....
}
Here tags is a string array.
I was wondering if there is a more elegant way to do this. Another thing to note is that the efficiency of this loop decreases as it progresses, since with more iterations it has to check more conditions. If we could remove a condition after it had become true once it would speed up each iteration since we know that each condition will become true only once in all the iterations
Moved answer about DataGridView and using ComponentModel to the correct question:
Displaying a list of object containing a list in a grid view
Briefing
The DataGridView controll supports the ComponentModel namespace so that you can create classes that appear to have properties that don't exist. It is the same mechanism the PropertyGrid uses.
The sample code is in this answer of that question:
https://stackoverflow.com/a/13078735/195417
OLD ANSWER
This was my previous answer, when I didn't realize the real question was about the DataGridView control.
Isn't this the same as setting the values directly:
this.tag1 = tags[0];
this.tag2 = tags[1];
this.tag3 = tags[2];
EDIT: as you sayd you don't know how many variables will be needed, then you need only one, and that is a list:
var list = new List<string>();
for (int i = 0; i < tags.Length; ++i)
{
list.add(tags[i]);
}
If all you want is to copy all values, you can even do this:
var list = new List<string>(tags);
Tell me whether this is what you want or not... maybe I have misunderstood the question.
The whole loop is pointless. But unless the tags array length is always going to be the same, you have to be sure not to go out of bounds...
if(tags.Length >= 1) this.tag1 = tags[0];
if(tags.Length >= 2) this.tag2 = tags[1];
if(tags.Length >= 3) this.tag3 = tags[2];
if(tags.Length >= 4) this.tag4 = tags[3];
if(tags.Length >= 5) this.tag5 = tags[4];
... so on for however many this.tag# you have.
This is essentially the same:
for(int index = 0; index < tags.Length[]; index++){
switch(index){
case 0:
tag1 = tags[0];
break;
// And so on
}
}

Append int to end of string or textbox name in a For Loop C#

I have a C# application in which there are several textboxes with the same name except for a number on the end which starts at 1 and goes to 19. I was hoping to use a for loop to dynamically add values to these text boxes by using an arraylist. There will be situations where there will not be 19 items in the arrayList so some text boxes will be unfilled. Here is my sample code for what I am trying to do. Is this possible to do?
for (int count = 0; count < dogList.Count; count++)
{
regUKCNumTextBox[count+1].Text=(dogList[count].Attributes["id"].Value.ToString());
}
So you've got a collection of text boxes that are to be filled out top-to-bottom? Then yes, a collection of TextBox seems appropriate.
If you stick your TextBox references in an array or a List<TextBox> -- I wouldn't use an ArrayList as it's considered deprecated in favor of List<T> -- then yes, you can do that:
TextBox[] regUKCNumTextBox = new []
{
yourTextBoxA,
yourTextBoxB,
...
};
Then yes your logic is possible, you can also query the control by it's name, though that would be heavier at runtime - so it's a tradeoff. Yes, in this solution you must set up a collection to hold your text box references, but it will be more performant.
Try this:
(By the way I am assuming you use WinForms)
for (int count = 0; count < dogList.Count; count++)
{
object foundTextBox = this.Controls.Find("nameofTextBoxes" + [count+1]);
if (foundTextBox != null)
{
if (foundTextBox is TextBox)
{
((TextBox)foundTextBox).Text=(dogList[count].Attributes["id"].Value.ToString());
}
}
}
With this code you are trying to find a Control form your Forms Controls collection. Then you have to make sure the control is of the TextBox type. When it is; cast it to a TextBox and do what you want with it. In this case; assign a value to the Text property.
It would be more efficient to keep a collection of your TextBoxes like in the solution offered by James Michael Hare
Yikes; something doesn't seem quite right with the overall design there; but looking past that, here's a quick stab at some pseudo code that might work:
for (int count = 0; count < dogList.Count; count++)
{
var stringName = string.Format("myTextBoxName{0}", count);
var ctrl = FindControl(stringName);
if(ctrl == null) continue;
ctrl.Text = dogList[count];
}

Categories