Swapping two button controls - c#

Having a bit trouble trying to figure out a way to swap 2 buttons. Let just dive in and show you the code:
int mCatID;
int mTempPos;
mCatID = mCatButList[mValidCatNumber - 1].mCatID - 1;
if (mTempOldPos.ToString() != txtCatPos.Text) // Attempt to change position
{
foreach (DataRow row in mIMenu.mCategoryList.Rows) // Check if space is taken
{
if (row[2].ToString() == txtCatPos.Text) // Space is taken
{
mCatOldIDX = mTempOldID - 2;
mTempDesc = mIMenu.mCategoryList.Rows[mCatOldIDX][1].ToString();
mIMenu.mCategoryList.Rows[mCatOldIDX][1] = row[1].ToString(); // desc
mIMenu.mCategoryList.Rows[mCatOldIDX][2] = (int)row[2]; // pos
row[1] = mTempDesc;
row[2] = mTempOldPos; //RP change new location to old
mCatOldIDX = 0;
mIMenu.mCategoryList.AcceptChanges();
break;
}
}
// mIMenu.mCategoryList.DefaultView.Sort = "POS asc";
CreateCatButList();
DisplayMenuCategories();
[EDIT] I have modified the code and now it seems that it does swap the position of the button controls once. But if I swap two of the controls and then swap one of the swapped buttons with another button it seems to mess up all the position values on all of the other buttons!? This is really starting to bug me.. why does it work for the first time and then not for others? Ive tried accept changes and still no effect.. Its all to do with the value in the Datatable mIMenu.mCategoryList where column [1] is Description and [2] is the Position. What is frustrating is why would it work once changing the value and then as soon as the state changes to modified decides to revert back to older position values?

Related

How can I change each duplicate set of values to different colour in DataGridView c#

I have a DataGridView with a Contact column full of numbers. Each number can reoccur multiple times, or just once.
I am trying to find a solution to re-colour each set of rows that contain matching numbers, but not recolour the ones with no duplicates.
Example of the outcome I am trying to achieve:
<p style="color:green;">2</p>
<p style="color:green;">2</p>
<p style="color:red;">3</p>
<p style="color:red;">3</p>
123 <br><br>
321 <br>
<p style="color:yellow;">4</p>
<p style="color:yellow;">4</p>
<p style="color:red;">3</p>
<p style="color:yellow;">4</p>
Here is my code, I think the problem is where I am incrementing the "duplicateCount" integer for the switch statement as I need it to increment only after every row containing the same value is coloured, but could not figure out a way to do that. Hoping I am clear enough and someone can guide me in the right direction. Thanks in advance
public void HighlightDuplicates(DataGridView grv)
{
List<String> alreadydone = new List<String>();
int duplicateCount = 1;
for (int currentRow = 0; currentRow < grv.Rows.Count - 1; currentRow++)
{
DataGridViewRow rowToCompare = grv.Rows[currentRow];
for (int otherRow = 0; otherRow < grv.Rows.Count-1; otherRow++)
{
DataGridViewRow row = grv.Rows[otherRow];
bool duplicateRow = true;
string rowToCompareString0 = rowToCompare.Cells[2].Value.ToString();
string rowString0 = row.Cells[2].Value.ToString();
if (rowToCompare.Cells[2].Value.ToString() != row.Cells[2].Value.ToString())
{
duplicateRow = false;
continue;
}
if (duplicateRow && currentRow != otherRow && !alreadydone.Contains(rowToCompare.Cells[2].Value.ToString() + rowToCompare))
{
switch (duplicateCount)
{
case 1:
rowToCompare.Cells[2].Style.BackColor = System.Drawing.Color.Red;
rowToCompare.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
row.Cells[2].Style.BackColor = System.Drawing.Color.Red;
row.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
alreadydone.Add(rowToCompare.Cells[2].Value.ToString() + rowToCompare);
break;
case 2:
rowToCompare.Cells[2].Style.BackColor = System.Drawing.Color.Yellow;
rowToCompare.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
row.Cells[2].Style.BackColor = System.Drawing.Color.Yellow;
row.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
alreadydone.Add(rowToCompare.Cells[2].Value.ToString() + rowToCompare);
break;
case 3:
rowToCompare.Cells[2].Style.BackColor = System.Drawing.Color.Green;
rowToCompare.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
row.Cells[2].Style.BackColor = System.Drawing.Color.Green;
row.Cells[2].Style.ForeColor = System.Drawing.Color.Black;
alreadydone.Add(rowToCompare.Cells[2].Value.ToString() + rowToCompare);
break;
default:
rowToCompare.Cells[2].Style.BackColor = System.Drawing.Color.Purple;
row.Cells[2].Style.BackColor = System.Drawing.Color.Purple;
alreadydone.Add(rowToCompare.Cells[2].Value.ToString() + rowToCompare);
break;
}
}
}
duplicateCount++;
}
}
It appears you may be over complicating things. It is unclear why your current code is using two for loops for this. One for loop will work and it will be less complicated.
The approach below simply loops through the rows in the grid and checks adjacent rows for equality. The only caveat here is that we need to color the first row FIRST. We know the first row will be colored since there is no “previous” row to compare it with.
Once this first row is colored, then we will loop through each row in the grid… HOWEVER, the for loop will not iterate to the LAST row. The loop will iterate to the second to the last row. With each iteration of the loop, we will check the “second” row to see if it equals the “previous” row and if so, we can color the second rows cell with the same color. If the cell values are not equal, then we will simply change the color of that cell to the next color.
It is unknown how many “different” colors you may want to use and, in the example below I used four (4) different colors and if the number of “different” cell values is greater than four (4), then we will simply start over with the first color used. In other words, the first and fifth groups of rows with “different” values will be colored the same and will repeat for every group of five different cell values.
To help, we will create a simple method called SetCellColor that will take an int curColor and a DataGridViewCell cell. In this method we will simply color the cell based on the given curColor. This method may look something like…
private void SetCellColor(int curColor, DataGridViewCell cell) {
switch(curColor) {
case 1:
cell.Style.ForeColor = Color.Red;
cell.Style.BackColor = Color.Black;
break;
case 2:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.Yellow;
break;
case 3:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.Green;
break;
case 4:
cell.Style.ForeColor = Color.Wheat;
cell.Style.BackColor = Color.Purple;
break;
}
}
This method above will make it easier to color the cell when we compare the two row’s cell values. We will use the above method in the method below which loops through the grid rows as described above. Keep in mind we need to set the loop to go from row zero (0), to the “SECOND” to last row. NOTE: this assumes the grids AllowUsersToAddRows property is set to false. If it is set to true then you will need to set the ending condition to Rows.Count – 2 to avoid a guaranteed null exception.
private void ColorDuplicateCells() {
int curColorIndex = 1;
SetCellColor(curColorIndex, dataGridView1.Rows[0].Cells[2]);
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) {
if (dataGridView1.Rows[i].Cells[2].Value.ToString() == dataGridView1.Rows[i + 1].Cells[2].Value.ToString()) {
SetCellColor(curColorIndex, dataGridView1.Rows[i+1].Cells[2]);
}
else {
curColorIndex++;
if (curColorIndex > 4) {
curColorIndex = 1;
}
SetCellColor(curColorIndex, dataGridView1.Rows[i + 1].Cells[2]);
}
}
}
Walking through the method, we color the first cell before we enter the for loop. Once in the for loop we compare the current row cells value with the next rows cell value. If the values are equal, then we will use the same color. If the values are different, then we will change to the next color by incrementing curColorIndex and then call the SetCellColor for the second row. Then continue on to the next row. In the else portion of the if statement, we need to check and make sure curColorIndex stays in bounds of the four (4) different colors. If the curColorIndex gets greater than four (4), then we will simply set it back to 1 and repeat the same color scheme for the rest of the rows.
I hope this makes sense.
Edit update per OP comment...
There are a couple of things that appear to be left out of you question. One question would be what do you plan on doing if the number of “duplicate” rows exceeds the number of “different” colors you use. In your example, you can clearly see the data and surmise that only four different (4) colors are needed. However, this may not always be the case and in my first answer I simply “repeat” the colors by repeating the four colors. This would mean that two or more rows of “different” values may have the same color.
Since I was under the impression the “different” values would be grouped together, then this strategy of repeating colors technically would work and still remove some ambiguity by the different values with the same color. Unfortunately, if the values are NOT “grouped” together, then ambiguity IS going to be an issue. In this case, with repeated colors, you could end up with two or more consecutive cells where ALL the values are different but the colors are the same…? …
The only way to avoid this ambiguity is to ensure that we have enough colors such that no color is used more than once. This is going to be dictated strictly by the data. This clearly points to looping through the data twice.
The first loop would be to figure out how many “different” colors are needed to avoid any ambiguity. How you do this is your call and, in the example below, the code sticks with the same strategy and simply repeats the colors if there are more “different” repeated rows than there are available colors… therefore ambiguity is guaranteed if there are not enough colors.
Next, it is unclear “how” the grid is getting filled with data. Typically, setting the grids DataSource to a List<SomeClass> or a DataTable is the preferred method to fill the grid with data. I will assume your code is “manually” adding the data directly to the grid cells and the grid does not use a data source. If this is true, you should re-think that approach to use a data source…
Casting UI DataGridViewRows/Cell to an enumerable type so you can select/filter/group the data is only extra work for you. If you use a data source for the grid, then selecting/filtering/grouping the DataSource as opposed to UI grid cells… becomes much easier and you can usually avoid the unnecessary casting of the UI cells. Bottom line, you need to do this grouping and counting using the DATA SOURCE NOT the grid cells. This is just a recommendation, pick your own poison. The example below uses a DataTable as a DataSource to the grid.
Given these issues, one approach is to loop through the data source DataTable to get a list of “different” duplicate rows. The approach you attempted sounds like a good approach… is what we want to get is a list of the row cell values that ARE duplicates. If a cell value is only used once, then, we do not want that value in the list. We can use this list to then loop through the grid rows and check each cells value to see if it is in the list. If it IS in the list, then that is a duplicate value and the cell needs to be colored. If the cells value is NOT in the list, then it is not a duplicated value and does not need to be colored.
The only problem here, is that we know the row is a duplicate… but what color should it be?... When we get the list of duplicate values, we need to assign a color to each of the distinct duplicate values. We could obviously create something to calculate this and in the example below, I simply used the index of the value in the list plus 1. Example, if the duplicate list has 5 items, then the first items (duplicate value) would be 0 + 1, the second item would be 1 + 1 etc.… this will enable us to use the same SetCellColor method created in the original answer and we do not have to create any extra variables.
The only change made to the method is I added a “default” value for the cells that are not duplicated. In that case we set the forecolor to black and the background to white. This will allow the code to color the non-duplicated cells to the proper colors. This updated method may look something like…
private void SetCellColor(int curColor, DataGridViewCell cell) {
switch(curColor) {
case 1:
cell.Style.ForeColor = Color.Red;
cell.Style.BackColor = Color.Black;
break;
case 2:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.Yellow;
break;
case 3:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.Green;
break;
case 4:
cell.Style.ForeColor = Color.Wheat;
cell.Style.BackColor = Color.Purple;
break;
case 5:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.Aqua;
break;
// more colors ?
default:
cell.Style.ForeColor = Color.Black;
cell.Style.BackColor = Color.White;
break;
}
}
And finally, the code that puts all this together may look something like below. duplicateItems is a list of only the rows such that the values are duplicated… it gets its items using the LINQ statement with the DATATABLE… not the grid rows. This is the first loop through the data.
Then we start a second loop though the grids rows. dupRow will contain the item from the duplicate list that matches that rows value. If dupRow returns null then that value is not in the duplicateItems list and we set the color index to zero (0). If dupRow is NOT null, then that row is a duplicate and we can set the color index to the index of the item in the duplicateaList plus 1. Once the colorIndex is set we can call the SetColorCell method. This code may look something like below…
Note: GridDT is a DataTable that is used as a DataSource to the grid. The values column [2] is named “DupCol”.
private void ColorCells() {
var duplicateItems = GridDT.AsEnumerable().GroupBy(x => x.ItemArray[2]).Where(y => y.Count() > 1).ToList();
int colorIndex;
foreach (DataGridViewRow row in dataGridView1.Rows) {
var dupRow = duplicateItems.FirstOrDefault(x => x.Key.Equals(row.Cells["DupCol"].Value.ToString()));
if (dupRow != null) {
colorIndex = duplicateItems.IndexOf(dupRow) + 1;
}
else {
colorIndex = 0;
}
SetCellColor(colorIndex, row.Cells["DupCol"]);
}
}
You are trying to do too much in one go. Things get much easier when you split them up.
First get the distinct values (using linq and from memory):
var distinctValues = grv.Rows.Select(r=>r.Cells[2].Value.ToString()).Distinct;
Then write a method to assign the colours:
Dictionary<string, System.Drawing.Color> AssignColours(IEnumerable<string> values)
{
// Add as many colours as you need here
System.Drawing.Color[] colours = new System.Drawing.Color[] {System.Drawing.Color.Red, System.Drawing.Color.Yellow, System.Drawing.Color.Green, System.Drawing.Color.Purple};
var result = new Dictionary<string, System.Drawing.Color>();
int currentColour = 0;
foreach (var s in values)
{
result[s] = colours[currentColour++];
}
return result;
}
And finally call the method and set the colour of the cells:
var colourDict = AssignColours(distinctValues);
for (int row = 0; row < grv.Rows.Count - 1; row++)
{
var cell = grv.Rows[row].Cells[2];
var value = cell.Value.ToString();
var backColour = colourDict[value];
cell.Style.BackColor = backColour;
cell.Style.ForeColor = System.Drawing.Color.Black;
}
EDIT
To not colour the unique values you need to change the expression to this:
var values = grv.Rows.Select(r=>r.Cells[2].Value.ToString();
var distinctValues = values.GroupBy(g=>g).Where(h=>h.Count()>1).Select(f=>f.Key).Distinct();
There might be a way to shorten that, but it works.
Then in the for-loop you need to take into account that the value might not be in the list:
var colourDict = AssignColours(distinctValues);
for (int row = 0; row < grv.Rows.Count - 1; row++)
{
var cell = grv.Rows[row].Cells[2];
var value = cell.Value.ToString();
if (colourDict.ContainsKey(value))
{
var backColour = colourDict[value];
cell.Style.BackColor = backColour;
cell.Style.ForeColor = System.Drawing.Color.Black;
}
}

how can i calculated values after Worksheet.Calculate()?

i tried Trial version of Gembox.SpreadSheet.
when i Get Cells[,].value by for() or Foreach().
so i think after Calculate() & get Cell[].value, but that way just take same time,too.
it take re-Calculate when i Get Cell[].value.
workSheet.Calcuate(); <- after this, values are Calculated, am i right?
for( int i =0; i <worksheet.GetUsedCellRange(true).LastRowIndex+1;++i)
{
~~~~for Iteration~~~
var value = workSheet.Cells[i,j].Value; <- re-Calcuate value(?)
}
so here is a Question.
Can i Get calculated values? or you guys know pre-Calculate function or Get more Speed?
Unfortunate, I'm not sure what exactly you're asking, can you please try reformulating your question a bit so that it's easier to understand it?
Nevertheless, here is some information which I hope you'll find useful.
To iterate through all cells, you should use one of the following:
1.
foreach (ExcelRow row in workSheet.Rows)
{
foreach (ExcelCell cell in row.AllocatedCells)
{
var value = cell.Value;
// ...
}
}
2.
for (CellRangeEnumerator enumerator = workSheet.Cells.GetReadEnumerator(); enumerator.MoveNext(); )
{
ExcelCell cell = enumerator.Current;
var value = cell.Value;
// ...
}
3.
for (int r = 0, rCount = workSheet.Rows.Count; r < rCount; ++r)
{
for (int c = 0, cCount = workSheet.CalculateMaxUsedColumns(); c < cCount; ++c)
{
var value = workSheet.Cells[r, c].Value;
// ...
}
}
I believe all of them will have pretty much the same performances.
However, depending on the spreadsheet's content this last one could end up a bit slower. This is because it does not exclusively iterate only through allocated cells.
So for instance, let say you have a spreadsheet which has 2 rows. The first row is empty, it has no data, and the second row has 3 cells. Now if you use 1. or 2. approach then you will iterate only through those 3 cells in the second row, but if you use 3. approach then you will iterate through 3 cells in the first row (which previously were not allocated and now they are because we accessed them) and then through 3 cells in the second row.
Now regarding the calculation, note that when you save the file with some Excel application it will save the last calculated formula values in it. In this case you don't have to call Calculate method because you already have the required values in cells.
You should call Calculate method when you need to update, re-calculate the formulas in your spreadsheet, for instance after you have added or modified some cell values.
Last, regarding your question again it is hard to understand it, but nevertheless:
Can i Get calculated values?
Yes, that line of code var value = workSheet.Cells[i,j].Value; should give you the calculated value because you used Calculate method before it. However, if you have formulas that are currently not supported by GemBox.Spreadsheet's calculation engine then it will not be able to calculate the value. You can find a list of currently supported Excel formula functions here.
or you guys know pre-Calculate function or Get more Speed?
I don't know what "pre-Calculate function" means and for speed please refer to first part of this answer.

C# Being Able to Search/Manipluate Existing RichTextBoxes That are Differently Named

With some of the knowledge I gained from yesterday and the day before, I have a general idea of what I want to do. I do have a general question about RichTextBoxes. I have a GUI already made of multiple RichTextBoxes aligned in different rows of one another. One row of boxes monitors the load of a product, the other monitors if one of the channels have been tripped and the other two rows displays the current and voltage of the product. The GUI has been premade and each row of product has been named StatusOutxxx, TripStatOutxxx, VoltageOutxxx and CurrentOutxxx (the xxx indicates a number of each RichTextBox, like CurrentOut001, for example).
The example gui is listed below:
From the image, you can see that I have 4 rows of RichTextBoxes. The monitoring backend of the product has already been established and I am trying to take the data and turn the product into a user friendly display to let the person now, if the load on a certain channel is okay or if the voltage of a product is too high/low or if a certain channel has been tripped.
Now, I know how to turn them all on at once via:
foreach(var rtb in this.Controls.OfType<RichTextBox>())
rtb.BackgroundColor = Color.Green;
and I know how to control which ones to turn on via if(rtb.Name.StartsWith("Insert Prefix Here")). But I am asking a bit of a harder question in terms of searching and manipulating an individual RichTextBox.
For example, if there is a load issue on Channel 17 of my product that drops my voltage, I want to be able to search for the StatusOut017, change the backcolor of that to Red and change the value of VoltageOut017 to the voltage display.
I know that the long way of doing it is doing a giant if statement for each load, trip and voltage channel to change it, but I am aiming for reducing the amount of lines of code and attempting to doing a for loop so my code will look something like this (in psuedocode):
for (i = 1; i < 25; i++)
{
if (StatusOut[i] == true)
{
StatusOut[i].BackColor == Color.Green;
}
else
{
StatusOut[i].BackColor == Color.Red;
}
if (TripStatOut[i] == true)
{
TripStatOut[i].BackColor == Color.Green;
}
else
{
TripStatOut[i].BackColor == Color.Red;
}
VoltageOut[i].Text = VoltageReading;
CurrentOut[i].Text = CurrentReading;
}
I am hoping for some help on this one.
I assume your naming convention is Name then 3 digits for the RichTextBox controls. You can use the controls collection to match the corresponding controls for that row. As noted a DataGrid would be better.
private void ChangeStatus()
{
//loop through the RichtextBoxes
foreach (RichTextBox rtb in this.Controls.OfType<RichTextBox>())
{
Color c = Color.Green; //default to good value
//only handle the status Out Control
if (rtb.Name.StartsWith("StatusOut"))
{ ///check the value and set the color if false
if (rtb.Text == "false")
c = Color.Red;
//update the controls
rtb.BackColor = c;
//string controlNum = rtb.Name.Replace("StatusOut", ""); //If it is not 3 just use replace since we know we are on the StatusOut control
string controlNum = rtb.Name.Substring(rtb.Name.Length - 3);
((RichTextBox)Controls["TripStateOut" + controlNum]).BackColor = c;
((RichTextBox)Controls["VoltageOut" + controlNum]).Text = VoltageReading;
((RichTextBox)Controls["CurrentOut" + controlNum]).Text = CurrentReading;
}
}
}

Method to remove text boxes from panel

I have a method in a windows form application that tries to remove 2 text boxes from a panel.
In the method, I loop through all the controls in the panel. There are always supposed to be 2 panels removed and added together, but when removing, it randomly removes 1 or 2 containers when I press the button.
Here is the code to remove the textboxes:
private void removeRows()
{
string descName = "Desc" + (textBoxCounter - 1).ToString();
string costName = "Cost" + (textBoxCounter - 1).ToString();
if (textBoxCounter >= 0)
{
foreach (Control c in costItems.Controls)
{
if (c.Name == descName)
{
// Remove the control from the panel and dispose of it
panel.Controls.Remove(c);
c.Dispose();
}
if(c.Name == costName)
{
// Remove the control from the panel and dispose of it
panel.Controls.Remove(c);
c.Dispose();
}
}
// Decrement the counter
// This happens only once since two controls need to be removed
if (textBoxCounter == 0)
textBoxCounter = 0;
else
textBoxCounter--;
}
else
MessageBox.Show("There are no more rows to remove", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
testlabel1.Text = textBoxCounter.ToString();
testlabel2.Text = panel.Controls.Count.ToString();
}
Here is the code to add a button:
private void addRows(string desc, string cost)
{
if (textBoxCounter >= maxExpenses)
{
MessageBox.Show("Maximum number of expenses entered", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
TextBox Desc = new TextBox();
TextBox Cost = new TextBox();
// Give the text boxes names
Desc.Name = "Desc" + textBoxCounter.ToString();
Cost.Name = "Cost" + textBoxCounter.ToString();
// Format the text boxes
Desc.Width = panel.Width / 2;
Cost.Width = panel.Width / 4;
// Add the items to the costItems panel
panel.Controls.Add(expenseDesc);
panel.Controls.Add(expenseCost);
// Add the items to the expenses dictionary
panel.Add(Desc, Cost);
// Increment the text box counter variable
textBoxCounter++;
testlabel1.Text = textBoxCounter.ToString();
testlabel2.Text = costItems.Controls.Count.ToString();
}
}
Some info to know.
There will always be 2 textboxes added and removed, they relate to each other.
The textBoxCounter is initialized to 0, so the first two boxe names will be "Desc0" and "Cost0".
When I press the button to remove rows the first time, one text box is removed, and then if i press it again it might remove 2, it might only remove 1.
I tried debugging and I noticed that the foreach loop that iterates over all the controls in the panel seems to loop one time short of the full number of controls.
Any help with my code would be great.
Your problem is caused by the foreach, modifying the collection in foreach may cause some unexpected behavior. You just want to remove the TextBoxes with names being known beforehand, so why not using the method ControlCollection.RemoveByKey?
If you want to remove the last added textBoxes (Desc... and Cost...) do this:
panel.Controls.RemoveByKey(descName);
panel.Controls.RemoveByKey(costName);
If you want to remove all the added textBoxes (suppose you have other kinds of TextBoxes, otherwise we can use a little LINQ to remove all the textboxes easily):
for(int i = 0; i < textBoxCounter; i++){
panel.Controls.RemoveByKey("Desc" + i);
panel.Controls.RemoveByKey("Cost" + i);
}
Your code has two problems: you are disposing something you cannot dispose and you are iterating through a collection (which you are modifying) in the wrong way. You can delete all the Controls by doing:
panel.Controls.Clear();
Or iterating backwards by relying on the indices:
for (int i = panel.Controls.Count - 1; i >= 0; i--)
{
panel.Controls.RemoveAt(i);
}
Regarding the Dispose, you can use it if you wish but don't need to use Remove:
for (int i = panel.Controls.Count - 1; i >= 0; i--)
{
panel.Controls[i].Dispose();
}
PS: I asked something identical to this and got -6. One of the reasons for maintaining this question was precisely being helpful to others (I saw the code you are using to delete controls in internet and I knew that quite a few people were using it). Pretty ironical, indeed.

Getting element of enum in array

I need to figure out how to get an element on an enum in an array.
Basically, I have a grid of 9x9 buttons. I have two multi-dimensional arrays that houses these values. One houses their names (if the name is 43) it means 5 down, 4 across (because they start at 0). The name is also the same as the ELEMENT of itself in the array.
string[,] playingField = new string[9, 9];
enum CellType { Empty, Flag, Hidden, Bomb }
CellType[,] cells = new CellType[9, 9];
the names of the buttons are held in playingField.
the status of each cell is held in cells (if it is empty, has a bomb, etc.)
Credit to AbdElRaheim for giving the above. The reason I'm doing this is so I can get a button name (exactly the same as the element name) which will be the same in both arrays.
For example: I can do this:
string dim1 = Convert.ToString(btn.Name[0]);
string dim2 = Convert.ToString(btn.Name[1]);
if (cells[Convert.ToInt32(dim1), Convert.ToInt32(dim2)] == CellType.Bomb)
(please excuse my terrible converting. i'll fix that up later ;)) and what the above does is it allows me to see if a cell that you click has a bomb under it.
However, what I need to do now, is essentially reverse of this. In the above I know the element name that I want to compare it to, because the element name is the same as the button name. However, now what I need to do is FIND the element name (button name) by getting the element of all elements that are Bomb in cells.
I'm not sure how to do this, I tried:
foreach (CellType Bomb in cells)
{
but it doesn't do anything. I need to find all 'bomb' in 'cells' and return the element name. That way I can use that element name, convert it to string, and use my StringToButton method to create a reference to the button.
This is the way I'm currently doing it, for reference, and to help you understand a little better, but take note this is NOT the way I want to continue doing it. I want to do it the way I asked about above :)
foreach (string i in minedNodes)
{
Button buttonName = StringToButton(Convert.ToString(i));
buttonName.Image = new Bitmap(dir + "mine.png");
}
Thanks!
If you are looking for a way to traverse your cells array, you would do this:
int oi, ii;
for (oi = 0; oi <= cells.GetUpperBound(0); ++oi)
{
for (ii = 0; ii <= cells.GetUpperBound(1); ++ii)
{
System.Diagnostics.Debug.WriteLine(
"Checking: " + oi + "," + ii + " : " + cells[oi, ii].ToString()
);
}
}
You can then save a list of references to cells[oi, ii] contents which match your desired value.

Categories

Resources