Get element by name - c#

I am trying to loop trough something 3 times and change the .text property of 3 element that have the names "label1", "label2" and "label3". I'm trying to add the 1,2,3 to the label but I can't get it to work.
this is what I'm trying to do:
the y is either 1,2 or 3
("label" + y).Text

I think you want this,so I make a simple code of it.
for(int i = 1; i <= 3; i++)
{
Console.WriteLine("label" + i);
}

if I understand correctly - you can do this using reflection:
var temp = (double)typeof(MyClass).GetProperty("label" + y).GetValue(myClassInstance);
if you change the type of MyClass to the class that holds your variable, myClassInstance to an instance of your class and the cast from double to your field type (which I'm guessing is some sort of WPF / Winforms control) you can get the variable by name.
It's important to note that your program will slow down if this is used often.

Related

c# getting values from using loop like combobox[i], i++

Hello i am working on some personal project,
I have lots of comboboxes in my project, which names are combobox1,combobox2 etc..
What i am trying to do is, getting combobox.text values respectively and do some work according to this.
Here is my code below;
for (i = 1; i <= geneList.Length; i++)
{
baserequest = "/" + comboBox[i].Text + ".docx";
sources.Add(new Source(new WmlDocument(basesource + geneList[i] + baserequest), false));
baserequest="";
DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Output.docx"));
}
so that actually not work. I searched but i think i missearching something because all i can get is about iterating through items, but what i want to do is exactly this;
comboBox[i].Text
Thank you very much.
If your comboboxes are named comboBox1, comboBox2 .... then you can't refer to comboBox2 using a syntax like comboBox[2]. This syntax means .. give me the third combobox stored in an array of comboboxes (and that should contain at least 3 elements)
So if you really want to use this syntax you need to create that combobox array somewhere in your code. After the call to InitializeComponent for example
public class Form1: Form
{
// declare the array as a global variable
private ComboBox[] combobox;
public Form1()
{
// Create and initialize all the elements of your form
// according to the properties set in the WinForms Designer
InitializeComponent();
// Choose all the individual comboboxes that you want to use
// inside your loops in the remainder of your code
combobox = new ComboBox[] { comboBox1, comboBox2, comboBox3 };
}
// all the code of your Form1 follows.....
}
A final note: You use a different array to create your loops. This array is named geneList and it should be kept in sync with the combobox array. Meaning the two arrays should have the same number of elements otherwise (if the geneList array is bigger than the combobox one you will get an ArgumentOutOfRangeException). Also array indexing start at index 0 not 1 so the usual loop is created with this syntax
for (i = 0; i < geneList.Length; i++)
Otherwise if you start from 1, as you do now, you skip the first element in the array and the last loop searches for an element that doesn't exist.

Out of bounds exception whilst using arrays

I have an array of textboxes in which they change dyanmically depending on what the user types in. Those textboxes contain a number which represents a score of an assignment. Those score are linked to a module object. So if the user has 3 modules; 2 assignments on the first and second module and 3 assignments on the third module; then in total there would be 7 textboxes created for the user to input all their assignment marks.
What I am trying to do is to create a keyup event handler in which it gets the number in typed in by the user, and then dynamically calls a method to display the average of the the module. This is what I have so far. The following method gets called whenever the user types in a character:
public void calculateLevel4Modules(int counter) {
//iterate through modules
//iterate through assignts in that module
//whilst iterating, check tb and set userscore
//after iterating, update overall label with regards to modulecounter
//int assignmentCounter = 0;
//Console.WriteLine("in If statement.. " + counter);
for (int moduleCounter = 0; moduleCounter < requiredLevelList().Count; moduleCounter++)
{
int totalNumberOfAssignmentsInCurrentModule = requiredLevelList().ElementAt(moduleCounter).Assignments.Count;
Console.WriteLine("total number of assignmetns: " + totalNumberOfAssignmentsInCurrentModule);
assignmentCounter = assignmentCounter + totalNumberOfAssignmentsInCurrentModule;
Console.WriteLine("assignment counter: " + totalNumberOfAssignmentsInCurrentModule);
if (counter < assignmentCounter)
{
Console.WriteLine("in If statement.. " + userMarksTBLvl4[moduleCounter].Text);
try
{
int userMark = int.Parse(userMarksTBLvl4[counter].Text);
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
double modAvg = requiredLevelList().ElementAt(moduleCounter).getModuleScoreOverall();
moduleOverallLvl4[moduleCounter].Text = modAvg.ToString();
break;
}
catch (FormatException) { break; }
}
else { }
}
it works fine if the user has one module but if the user has two or more, then I get an error in the following line:
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
I am getting an out of bounds exception. I know why; its because counter is basically the # of the textbox that was typed into but by me using counter, I am accessing something not within the assignments list. This is an example of when the problem occus:
The user has 2 modules. In each module there are 2 assignments thus 4 textboxes are been created with their index ranging from 0 - 3. If the user wants to type in their score of the first assignment on the second module, its basically trying to write to the third index in that element then it crashes since that module only consist of 2 assignments.
There are some strange things in your code that make it hard to answer. First, the code you posted doesn't compile, so we have no way to test it.
Several times you use code like:
requiredLevelList().ElementAt(moduleCounter)
I assume requiredLevelList is a method that returns a list of things. There is no reason to assume requiredLevelList returns the same list, or even lists with the same number of elements, each time you call it. Maybe it does in your particular case, but this is a dangerous thing to rely on. You should use a construct like:
foreach (var module in requiredLevelList())
{
int totalNumberOfAssignmentsInCurrentModule = module.Assignments.Count;
...
module.Assignments.ElementAt(counter).UsersScore = userMark;
...
}
Code like this:
Console.WriteLine("total number of assignmetns: " + totalNumberOfAssignmentsInCurrentModule);
is symptomatic of trying to debug something after it has crashed. That is extremely inefficient. Learn how to use a debugger; you will not become an effective programmer until you know how to do this.
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
You're probably getting an out-of-bounds exception here because counter is outside the indexes of Assignments. Since you never initialize or change counter, I have no way to know what it is or should be. A debugger will tell you this, use one.
the # of the textbox that was typed into but by me using counter, I am accessing something not within the assignments list.
OK, if you're typing something “not within the assignments list” then you have to test for that and decide what to do. Perhaps something like:
if (counter >= 0 && counter < module.Assignments.Count)
module.Assignments.ElementAt(counter).UsersScore = userMark;
else
throw new Exception("I really have no idea what you want to do here.");
This also looks wrong:
moduleOverallLvl4[moduleCounter].Text = modAvg.ToString();
You never tell us what moduleOverallLvl4 is, but here you're assuming it has the same size as what is returned by requiredLevelList(). Maybe they are in this particular case, but that is a dangerous assumption. If these values are related, moduleOverallLvl4 should be contained in whatever class implements requiredLevelList, and you should have a method that assigns getModuleScoreOverall() to the correct element of moduleOverallLvl4.

ObjectListView - Displaying arrays

Suppose I have this code:
public sealed class MyStruct {
// ... snip
public uint[] ItemStatValue { get; set; }
// ... snip
}
// MainForm.cs
// ...
Generator.GenerateColumns(this.ContentListView, structure, true);
ContentListView.SetObjects(_records);
// ...
Is there a way to instruct GenerateColumns to treat each element of the ItemStateValue property as a column on its own, and appropriately name them ? ("Item Stat Value 1", "Item Stat Value 2", etc) Currently, it just calls ToString() on the object, thus returning System.Type.UInt32[]. Not exactly what I'd want.
I'm using http://www.codeproject.com/Articles/16009/A-Much-Easier-to-Use-ListView
Cheers!
No, that is not possible. The OLV uses reflection on the type of the specified item to gather the required information. If you supply an IEnumerable it just looks at the type of the first item.
The Generator has no clue and does not care about the actual instances of your items. Also, it wouldn't make much sense in your proposed case, since the number of elements could differ between each struct.
How many items are going to be in the array? ListViews have a fixed number of columns, i.e. each row has the same number of columns.
If you know there is going to be, say, 20 possible stats, just generate the columns.
const int numberOfColumns = 20;
for (int i = 0; i < numberOfColumns; i++) {
var statIndex = i;
var column = new OLVColumn();
column.Name = "Stat" + i;
column.AspectGetter = delegate(object x) {
MyStruct myStruct = (MyStruct)x;
return statIndex < myStruct.ItemStatValue.Length ? (uint?)myStruct.ItemStatValue[statIndex] : null;
};
column.AspectToStringConverter = delegate(object x) {
uint? value = (uint?)x;
return value.HasValue ? String.Format("Stat value: {0}", value.Value) : String.Empty;
};
this.ContentListView.AllColumns.Add(column);
}
this.ContentListView.RebuildColumns();
Call this after the GenerateColumns()
#Grammarian
So after looking around in the code, I noticed aspect getters for fields. However, Generator.GenerateColumns didn't seem to use its third boolean parameter, named allProperties.
So I threw together this quick code, and sure enough, it worked. It doesn't seem to cause any bug either, which is great.
Here is a gist:
https://gist.github.com/Warpten/c792ad66ad20cc69a918
Note: this also requires that you allow OLVColumnAttribute and OLVIgnoreAttribute to be applied to fields. That's easy enough ;)
Cheers!

RadioButton.Checked issue

So I am having a bit of issue with this piece of code for a class of mine. I know it seems rather elementary but for the life of me I am not sure why I can't get it to work.
Essentially I have 6 radio buttons and depending on which one is selected I want to assign a value to an int variable. I want to return that value to another winForm which will do something else.
but for some reason it always returns 0.
some help would be greatly appreciated.
Thank you in advance..
int x = 0;
public int selectionDie1()
{
if (die1_1.Checked)
x = 1;
if (die1_2.Checked)
x = 2;
if (die1_3.Checked)
x = 3;
if (die1_4.Checked)
x = 4;
if (die1_5.Checked)
x = 5;
if (die1_6.Checked)
x = 6;
return x;
}
I like to also add that even if I change this to a void with no return value and place a label that would display the value of x on buttonclick, it still returns a 0.
I have even tried using just one radiobutton and see if that would work, nothing at all.
when I set x = 1000; and return that it works fine, so it has to do with the radio buttons
thank you
If I understand this correctly, you are attempting to use the variable x in your other form. You need to use the direct result of the selectionDie1 function.
public int selectionDie1()
{
if (die1_1.Checked)
return 1;
else if (die1_2.Checked)
return 2;
...
else
throw new exception("there was no item checked");
}
This way there is no variable to keep track of, or could be accessed from an outside location.
The other issue is that you are creating a form and then immediately checking for the selected item (if your comment is correct). You need to first create and show the form, give the user time to choose an option, and then do this function call (which might happen on a user selection, form close, button press, etc).

C# - Compile variable as name/code

Since I couldn't explain very good in my last question and I didn't get an answer that could satisfy me, I decided to open a new one. Straight to the point, what I'm basically trying to do is compiling a variable (the value it holds) as a part of code (and specificly in my case referencing another variable)
Say I have:
int var_1, var_2, var_3 ... var_10;
for (int i = 1; i <= 10; i++)
{
var_%i%=20; //if i is 1, then var_1's value will be set to 20, if i is 2, then var_2's value will be set to 20. So basically this loop sets the value of var_1 .. var_10 to 20
}
I can explain in an even simpler way, if in any case the latter is not clear.
int var_5;
int SomeOtherVar = 5;
var_%SomeOtherVar% = 10; // so var_5 (where 5 is the value of SomeOtherVar) is set to 10
Is this doable and if it is, what's the approach?
No you can't do that, why dont you use an array?
int[] array = new int[3];
for (int i = 0; i < array.Length; ++i)
{
array[i] = 20;
}
Hope it helps.
It's not doable. Use an array instead. The type is int[] but I suggest you go read a tutorial about arrays to understand how to create and use them.
I can't think of a situation where you'd need to do this. If you wish to store values against a consecutive list of numbers, use an array. Otherwise you could use a Dictionary. For example to store "var1" = 20, "var2" = 20 as in your question, you could do this:
Dictionary<string, int> dict = new Dictionary<string, int>();
for (int i = 1; i <= 10; i++)
{
dict.Add("var" + i.ToString(), 20);
}
Some examples of usage:
dict["var1"] // 20
dict["var2"] // 20
dict.ContainsKey("var3") // true
dict.ContainsKey("var99") // false
Note: I'm concatenating the string "var" with the int from the loop just to demonstrate that you can use arbitary strings as keys to store / lookup the values. In this case it's a bit of a strange thing to do, and you'd probably be best sticking to a normal array, but my example shows how a dictionary could work with more complex keys.
If you want to bypass static type checking and you feel like creating some coding horror, you can use ExpandoObject combined with the dynamic keyword. Won't let you set variables in your scope, but will technically let you declare your own ones. Note that in my example I cast it to IDictionary<string, object> because I create its members' names at runtime from a string. What the following method does is create twenty members and assign their values from 0 to 19.
static dynamic SetVariables(IEnumerable<int> range)
{
const string variableName = "var_";
var expandoDictionary = new ExpandoObject() as IDictionary<string, object>;
foreach (var i in range)
expandoDictionary[variableName + i] = i;
return expandoDictionary;
}
You can then access the members easily this way:
var container = SetVariables(Enumerable.Range(0, 20));
var value13 = container.var_13;
Please note that I do not recommend this usage, and I'd stay away from dynamic as much as I can. However, for the sake of problem solving, this can be seen as one unsafe but partial solution.

Categories

Resources