I am creating a grid of buttons using the following code:
Button[][] buttons;
In the method:
for (int r = 0; r < row; r++)
{
for ( int c = 0; c < col; c++)
{
buttons[r][c] = new Button();
}
}
How can I clear and reset buttons[][] if row or col changes, is there away to do it?
Yes, there is. You can call the Array.Clear() function. Since your array holds Button objects, which are reference types, it will reset every item in the array to null.
Array.Clear(buttons, 0, buttons.Length);
However, I strongly suggest using one of the generic containers for this, rather than a raw array. For example, a List<T> would be a good choice. In your case, T would be Button.
using System.Collections.Generic; // required at the top of the file for List<T>
List<Button> buttons = new List<Button>();
To use it like a two-dimensional array, you will need a nested list (basically, a List that contains a List that contains Button objects). The syntax is a little intimidating, but it's not so hard to figure out what it means:
List<List<Button>> buttons = new List<List<Button>>();
you can invoke Clear() Method
http://msdn.microsoft.com/en-us/library/system.array.clear.aspx
Related
To clarify my question more I'll first show you add a checkbox using the blazor component library I'm using:
<MudCheckBox #bind-Checked="#Basic_CheckBox1"></MudCheckBox>
#code{
public bool Basic_CheckBox1 { get; set; } = false;
}
the code above creates a checkbox and then toggles the boolean Basic_CheckBox1 to true or false based on if the checkbox is checked or not.
here is my code
#for (int i = 0; i < checkboxNames.Count; i++)
{
<MudCheckBox #bind-Checked="#checkboxBools[i]" Label="#checkboxNames[i]"></MudCheckBox>
}
this code works until I check or uncheck my created checkboxes, then I get the index out of range error, how can I fix this? I need to use a list of booleans because I don't know how many checkboxes I will need until runtime, if there is any other solution please let me know.
Think of it like the bind isn't done there and then in the loop, but later. By the time the bind comes to be done, the value of i is off the end of the array Length, having been incremented repeatedly. Instead, you can save the current value of your loop variable i into another variable, then use that other variable in your bind:
#for (int i = 0; i < checkboxNames.Length; i++)
{
var x = i;
<MudCheckBox #bind-Checked="#checkboxBools[x]" Label="#checkboxNames[i]"></MudCheckBox>
}
checkBoxBools should be an array/list that is the same length (initalized to have the same number of elements as) checkBoxNames.. For example:
string[] checkboxNames = new string[]{"a","b","c"};
bool[] checkboxBools = new bool[3];
Or, if something else is providing a variable number of names:
checkboxNames = context.People.Select(p => p.Name).ToArray();
checkboxBools = new bool[checkBoxNames.Length];
https://try.mudblazor.com/snippet/GamQEFuFIwdRbzEx
I found this question but it's being used with an XML file so I don't really understand what is going on.
What I want to do is get my list of objects to get populated in my for loop. Right now I have this:
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
}
dogs[0].PictureBox = picDog0;
dogs[1].PictureBox = picDog1;
dogs[2].PictureBox = picDog2;
dogs[3].PictureBox = picDog3;
I want to do something like this:
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
dogs[i].PictureBox = StringToVariable("picDog" + i);
}
PictureBox is a property field in case that makes a difference.
StringToVariable() is the thing I don't know about. I don't even know what it would be called to search for it.
It's impossible to say for sure without a good, minimal, complete code example. But I would expect that the following statement should work in your scenario:
dogs[i].PictureBox = (PictureBox)Controls.Find("picDog" + i, true)[0];
That will search the children of the current control (which I assume in this case is your Form subclass) for each control in turn. This is somewhat inefficient, as it has to search the controls collection for each item, but as long as you have a relatively small number of items, this is likely not a problem.
Depending on how your Form is set up, the following might also work:
string prefix = "picDog";
foreach (PictureBox pictureBox in Controls.OfType<PictureBox>())
{
if (pictureBox.Name.StartsWith(prefix))
{
int index;
if (int.TryParse(pictureBox.Name.Substring(prefix.Length), out index))
{
dogs[index] = pictureBox;
}
}
}
That version inspects each child control just once, attempting to parse an index appended to the initial text of "picDog", and if it's successful, using that index to assign to your array directly. This has the advantage of scaling well to larger lists of controls, but may be overkill in your case.
Note that in both of the above examples I've left out any error checking. In either example, you would probably want to add some kind of handling in case (for the first example) the desired control couldn't be found, or (for the second example) if you find a control for which you can't parse the index, or fail to fill in one of the elements of the dogs array.
If for some reason neither of the above examples seem to work for you, please edit your post so that it includes a better code example.
Sometimes a simple solution can work well. How about this?
var picDogs = new [] { picDog0, picDog1, picDog2, picDog3 };
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
dogs[i].PictureBox = picDogs[i];
}
You could even do this:
var dogs = new [] { picDog0, picDog1, picDog2, picDog3 }
.Select(picDog => new Dog() { PictureBox = picDog })
.ToArray();
I have 100 buttons in a panel. They are named btn1-btn100. I am trying to put them into a list. This is what i have so far:
public void buttonList()
{
List<Button> panelButtonList = new List<Button>();
for (int x = 1; x <= 100; x++)
{
panelButtonList.Add(btn + x);
}
}
the name btn doesn't exist in current context? I'm new would be greatful for any assistance
List<Button> panelButtonList = this.YourPanel.Controls.OfType<Button>().ToList();
Try the above. You might have to add a where clause if there are other buttons that you don't want included. If needed you can white list based on the id range.
You need to use a FindControl method. Build your control name "btn"+Convert.ToString(x)
Hi when I create textboxes on Windows Application Form I cannot name it as box[0], box[1] and so on. The purpose why I want to do like this is because I want to use them in a loop.
Actually I found TextBox[] array = { firstTextBox, secondTextBox }; works too!
How about making a list of them after you create them? In your form initialization function, you can do something like:
List<TextBox> myTextboxList = new List<TextBox>();
myTextBoxList.Add(TextBox1);
myTextBoxList.Add(TextBox2);
mytextBoxList.Add(TextBox3);
Now you can itterate through with your "myTextboxList" with something like below:
Foreach (TextBox singleItem in myTextboxList) {
// Do something to your textboxes here, for example:
singleItem.Text = "Type in Entry Here";
}
You can create textboxes on runtime and just put them in an array...
If you want to do it in design time, you will have to do some control filtering logic on the whole this.Controls array in order to access only the wanted textboxes. Consider if (currControl is TextBox) if all textboxes in the form are ones you want in the array.
Another option for design time, is putting all wanted textboxes in a panel which will be their parent, and then iterating over the panel's children (controls) and cast them to TextBox.
A runtime solution would be something like:
var arr = new TextBox[10];
for (var i = 0; i < 10; i++)
{
var tbox = new TextBox();
// tbox.Text = i.ToString();
// Other properties sets for tbox
this.Controls.Add(tbox);
arr[i] = tbox;
}
I wouldn't use an array for this, personally. I would use some form of generic collection, like List.
List<TextBox> textBoxList = new List<TextBox>();
//Example insert method
public void InsertTextBox(TextBox tb)
{
textBoxList.Add(tb);
}
//Example contains method
public bool CheckIfTextBoxExists(TextBox tb)
{
if (textBoxList.Contains(tb))
return true;
else
return false;
}
You don't necessarily have to use the Contains method, you could also use Any(), or maybe even find another way- all depends on what you're doing. I just think using a generic collection gives you more flexibility than a simple array in this case.
for C# just use this to create an array of text boxes
public Text [] "YourName" = new Text ["how long you want the array"];
then add the text boxes to the array individually.
TextBox Array using C#
// Declaring array of TextBox
private System.Windows.Forms.TextBox[] txtArray;
private void AddControls(int cNumber)
{
// assign number of controls
txtArray = new System.Windows.Forms.TextBox[cNumber + 1];
for (int i = 0; i < cNumber + 1; i++)
{
// Initialize one variable
txtArray[i] = new System.Windows.Forms.TextBox();
}
}
TextBox[] t = new TextBox[10];
for(int i=0;i<required;i++)
{
t[i]=new TextBox();
this.Controls.Add(t[]);
}
I can quickly clear the selection of a ListView using its SelectedIndices.Clear method, but if I want to select all the items, I have to do this:
for (int i = 0; i < lv.SelectedIndices.Count; i++)
{
if (!lv.SelectedIndices.Contains(i))
lv.SelectedIndices.Add(i);
}
and to invert the selection,
for (int i = 0; i < lv.SelectedIndices.Count; i++)
{
if (lv.SelectedIndices.Contains(i))
lv.SelectedIndices.Add(i);
else
lv.SelectedIndices.Remove(i);
}
Is there a quicker way?
Use the ListViewItem.Selected property:
foreach(ListViewItem item in lv.Items)
item.Selected = true;
foreach(ListViewItem item in lv.Items)
item.Selected = !item.Selected;
EDIT: This won't work in virtual mode.
To quickly select all the items in a ListView, have look at the long answer to this question. The method outlined there is virtually instantaneous, even for lists of 100,000 objects AND it works on virtual lists.
ObjectListView provides many helpful shortcuts like that.
However, there is no way to automatically invert the selection. SLaks method will work for normal ListViews, but not for virtual lists since you can't enumerate the Items collection on virtual lists.
On a virtual list, the best you can do is something like you first suggested::
static public InvertSelection(ListView lv) {
// Build a hashset of the currently selected indicies
int[] selectedArray = new int[lv.SelectedIndices.Count];
lv.SelectedIndices.CopyTo(selectedArray, 0);
HashSet<int> selected = new HashSet<int>();
selected.AddRange(selectedArray);
// Reselect everything that wasn't selected before
lv.SelectedIndices.Clear();
for (int i=0; i<lv.VirtualListSize; i++) {
if (!selected.Contains(i))
lv.SelectedIndices.Add(i);
}
}
HashSet is .Net 3.5. If you don't have that, use a Dictionary to give fast lookups.
Be aware, this will still not be lightning fast for large virtual lists. Every lv.SelectedIndices.Add(i) call will still trigger a RetrieveItem event.
You can just set the Selected property of the ListViewItem class.