how can i access a textbox which create dynamically? - c#

when i creat unlimited textbox in gridview dynamically how can i access them?
for example:
int uste_uzaklik = 30;
int nesne = ListBox1.Items.Count;
Array.Resize(ref textboxarray, nesne * nesne);
for (int str = 0; str < nesne; str++)
{
for (int stn = 0; stn < nesne; stn++)
{
textboxarray[idm] = new TextBox();
textboxarray[idm].Font.Bold = true;
textboxarray[idm].Font.Name = "Verdana";
textboxarray[idm].ID = idm.ToString();
textboxarray[idm].ToolTip = textboxarray[idm].ID;
GridView2.Rows[str].Cells[stn + 1].Controls.Add(textboxarray[idm]);
if (str == stn) textboxarray[idm].Enabled = false;
uste_uzaklik += 30;
idm++;
}
}
i add texboxes in gridview...you can imagine a matris...
there is no problem...
but when i access them like this:
if (((TextBox)(GridView2.Rows[str].Cells[stn].FindControl(idm.ToString()))).Text != null)
{
matris[i, j] = Convert.ToInt32(GridView2.Rows[str].Cells[stn].Text);
}
occur an error
Object reference not set to an instance of an object.
how can i solve this problem?

References you have to controls don't cease to exist you add them to another control. You've already created an array of your TextBoxes, and you should use that to access them instead of trying to dig into the GridView in which you've added them every single time you want to change them.
Granted, you're going from a one-dimensional array of TextBoxes to a two-dimensional layout within the GridView, so you'll either have to find some way to establish how the indices match up between the two. Or, more easily, you could just turn textboxarray into a two-dimensional array and just have it exactly match the way it's laid out in the GridView. Either way, I think it'll be a lot less work than having to muck around in the GridView.

Related

Creating a sudoku. Should I use a while statement for this code?

I'm making a sudoku in Windows Form Application.
I have 81 textboxes and I have named them all textBox1a, textBox1b... textBox2a, textBox2b...
I want to make it so that if any of the textboxes, in any of the rows, is equal to any other textbox in the same row, then both will get the background color red while the textboxes are equal.
I tried using this code just for test:
private void textBox1a_TextChanged_1(object sender, EventArgs e)
{
while (textBox1a.Text == textBox1b.Text)
{
textBox1a.BackColor = System.Drawing.Color.Red;
textBox1b.BackColor = System.Drawing.Color.Red;
}
It didn't work, and I don't know where I should put all this code, I know I shouldn't have it in the textboxes.
Should I use a code similar to this or is it totally wrong?
You want to iterate over the collection of text boxes just once, comparing it to those that haven't yet been compared against. If you have your textboxes in an array (let's call it textBoxes), and know which one was just changed (e.g. from the textChanged handler), you could do:
void highlightDuplicates(int i) // i is the index of the box that was changed
{
int iVal = textBoxes[i].Text;
for (int j = 0; j < 82; j++)
{
// don't compare to self
if (i == j) return;
if (textBoxes[j].Text == iVal)
{
textBoxes[i].BackgroundColor = System.Drawing.Color.Red;
textBoxes[j].BackgroundColor = System.Drawing.Color.Red;
}
}
}
If you wanted to get fancier, you could put your data in something like: Dictionary<int, TextBox>, where the key is the value and the TextBox is a reference to the text box with that value. Then you can quickly test for duplicate values with Dictionary.Contains() and color the matching text box by getting its value.
I think your current code would result in an infinite loop. The textboxes' values can't change while you are still in the event handler, so that loop would never exit.
If all of your boxes are named according to one convention, you could do something like this. More than one input can use the same handler, so you can just assign this handler to all the boxes.
The following code is not tested and may contain errors
private void textBox_TextChanged(object sender, EventArgs e){
var thisBox = sender as TextBox;
//given name like "textBox1a"
var boxNumber = thisBox.Name.SubString(7,1);
var boxLetter = thisBox.Name.SubString(8,1);
//numbers (horizontal?)
for(int i = 1; i<=9; i++){
if(i.ToString() == boxNumber)
continue; //don't compare to self
var otherBox = Page.FindControl("textBox" + i + boxLetter) as TextBox;
if (otherBox.Text == thisBox.Text)
{
thisBox.BackColor = System.Drawing.Color.Red;
otherBox.BackColor = System.Drawing.Color.Red;
}
}
//letters (vertical?)
for(int i = 1; i<=9; i++){
var j = ConvertNumberToLetter(i); //up to you how to do this
if(j == boxLetter)
continue; //don't compare to self
var otherBox = Page.FindControl("textBox" + boxNumber + j) as TextBox;
if (otherBox.Text == thisBox.Text)
{
thisBox.BackColor = System.Drawing.Color.Red;
otherBox.BackColor = System.Drawing.Color.Red;
}
}
}
I believe you will be more effective if create an Array (or a List) of Integers and compare them in memory, against compare them in UI (User Interface).
For instance, you could:
1) Create an Array of 81 integers.
2) Everytime the user input a new number, you search for it in that Array. If found, set the textbox as RED, otherwise, add the new value to that array.
3) The ENTER event may be allocated fot the entire Textboxes (utilize the Handles keyword with all Textboxes; like handles Text1.enter, Text2.enter, Text3.enter ... and so forth)
Something like:
int[] NumbersByUser = new int[81];
Private Sub Textbox1.Enter(sender as object, e as EventArgs) handles Textbox1.Enter, Textbox2.Enter, Textbox3.enter ...
int UserEntry = Convert.ToInt32(Sender.text);
int ValorSelecionado = Array.Find(NumbersByUser, Z => (Z == UserEntry));
if (ValorSelecionado > 0) {
Sender.forecolor = Red;
}
else
{
NumbersByUser(Index) = UserEntry;
}
You should have a 2 dimensional array of numbers (could be one dimensional, but 2 makes more sense) let's assume its called Values. I suggest that you have each textbox have a incrementing number (starting top left, going right, then next row). Now you can do the following:
All TextBox Changed events can point to the same function. The function then takes the tag to figure out the position in the 2dim array. (X coordinate is TAG % 9 and Y coordinate is TAG / 9)
In the callback you can loop over the textboxes and colorize all boxes as you like. First do the "check row" loop (pseudo code)
var currentTextBox = ((TextBox)sender)
var x = ((int)currentTextBox.Tag) % 9
var y = ((int)currentTextBox.Tag) / 9
// First assign the current value to the backing store
Values[currentTextBox] = int.parse(currentTextBox.Text)
// assuming variable x holding the column and y holding the row of current box
// Array to hold the status of a number (is it already used?)
bool isUsed[9] = {false, false, ...}
for(int col = 0; col <= 9; i++)
{
// do not compare with self
if(col == x) continue;
isUsed[textBox] = true;
}
// now we have the status of all other boxes
if( isUsed[Values[x,y]] ) currentTextBox.Background = Red else currentTextBox.Background = Green
// now repeat the procedure for the column iterating the rows and for the blocks
I would suggest a dynamic approach to this. Consider each board item as a cell (this would be it's own class). The class would contain a numeric value and other properties that could be useful (i.e. a list of possible values).
You would then create 3 collections of the cells, these would be:
A collection of rows of 9 cells (for tracking each row)
A collection of columns of 9 cells (for tracking each column)
A collection of 3x3 cells
These collections would share references - each cell object would appear once in each collection. Each cell could also contain a reference to each of the 3 collections.
Now, when a cell value is changed, you can get references to each of the 3 collections and then apply a standard set of Sudoku logic against any of those collections.
You then have some display logic that can walk the boards of cells and output to the display (your View) your values.
Enjoy - this is a fun project.

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.)

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];
}

C# Assign to an Array with many NumericUpdown Objects

Ok so I am making a sudoku solver for fun (yes I know it's already been made many times over) so to let people input there values before solving I used numericalupdown (81 one of them to be exact)
and i wanted to assign all of them to an array:
int[,] Sudoku = new int[9, 9];
and then on clicking "solve" the first thing it's supposed to do is put all the values in the array:
private void button1_Click(object sender, EventArgs e)
{
for (int x = 0; x < 81; x++)
{
for (int y = 0; y < 9; y++)
{
if (x-1 == 0)
{
Sudoku[x - 1, y - 1] = Convert.ToInt32(numericUpDown[y].Value);
}
else
{
Sudoku[x - 1, y - 1] = Convert.ToInt32(numericUpDown[x][y].Value);
}
}
}
}
obviously you can't do: "numbericupdown[y]" but thats for you to see what I am trying to do....
sooooo thoughts?
THANKS,
Craiggles
If you put your numericUpDown controls into a 9x9 grid just like you have for the results, then copying the values will be straightforward.
private void button1_Click(object sender, EventArgs e)
{
for (int x = 0; x < 9; x++)
{
for (int y = 0; y < 9; y++)
{
Sudoku[x, y] = Convert.ToInt32(numericUpDown[x, y].Value);
}
}
}
If the controls are actually all dropped onto the form, then don't do that, remove them from the form. Use code to create them, place them programmatically, and put them into a 2d array. Since this is a learning program anyways, that's good practice for doing GUI's programmatically instead of just by drag-n-drop.
I would go about constructing/placing them dynamically and at the same time putting them into an array or list, but if they are already laid out onto a form you can just add them to a generic list to iterate over them.
List<NumericUpDown> nums = new List<NumericUpDown>();
nums.add(numericUpDwown1);
then you could calculate nums[1]*nums[9]... or whatever
I think I understand what you are doing... Two suggestions: 1) put all of your controls into an array of NumericaUpDown objects. Then you could do numericUpDown[y].Value. Otherwise, 2) name the controls ending with numbers (or some similar convention) then use reflection to find the right one and get its value.
Actually there is no reason at all why you cannot create controls and store them in various collection classes - not just arrays.
I would consider putting these into some sort of structured set of collections that reflect the structure of a sudoku grid.
You could dynamically create and place the controls on the form as well as holding them in the collection.

Programatically reference ascending variable names (var1, var2, ... )

I'm currently coding a project that can take up to 200 entries of a specific product, as determined by user input. Basically, my GUI loads, and I use jQuery to dynamically build the entries whenever there is a change to the amount field. When using jQuery, I simply give each of them ids in the form of variable1, variable2, ...., variableX (where X is the amount of entries indicated). Small snippet of code to clarify:
for(var i = 1;i <= amount_selected; i++) {
$('table_name tr:last').after('<tr><td><input type="text" id="variable' + i + '"></td></tr>');
}
Now when I try to move to the back end, I'm trying to reference these variable names by putting them in a list. I went ahead and put them in a list of HtmlInputText, to call the Variable names from the list itself. (This would save having to call all (up to 200) methods manually, which is really not an option).
So what I did (in C#) was:
List<HtmlInputText> listvar = new List<HtmlInputText>();
for(int i = 1; i <= amount_selected; i++) {
string j = "variable" + Convert.ToString(i);
HtmlInputText x = j;
listvar.Add((x));
samplemethod(listvar[i]);
}
But it's not working at all. Does anyone have any ideas as to how this would be done, without doing so manually? I know my logic might be completely off, but hopefully this illustrates at least what I'm attempting to do.
I'm assuming these inputs are in a form? If you're submitting then you can access the text boxes from the Request object:
List<string> results = new List<string>();
for (int i = 1; i <= amount_selected; i++)
{
string s = String.Format("{0}", Request.Form["variable" + Convert.ToString(i)]);
results.Add(s);
}
you could do $("#variable" + Convert.ToString(i)).val()

Categories