Randomly check items in checklistbox - c#

I have a checklistbox and I want to randomly check a set number of the items in the textbox (CheckAmount.Text) - i.e. if the user enter 60%(0.60), I want 60% of the items in the checked listbox to be checked. Is this possible or even close?
int CA = Convert.ToInt32(CheckAmount.Text);
for (int i = 0; i <= CA; i++)
{
}

I can get close, but what you are saying is to:
Check blah amount of CheckBoxes in CheckBoxList foo
Code:
//The CheckBoxList name is boxes
int CA = Convert.ToInt32(CheckAmount.Text);
Random rng = new Random();
int x = 0;
for (int y = CA; y != 0; y--)
foreach (CheckBox i in boxes.Controls)
{
x = rng.Next(1, boxes.Length + 1); //have to add 1 or it will never pick the last box
if(boxes[boxes.Controls.IndexOf(i)] == x - 1)
{
i.Checked = true;
y--;
}
else
{
continue;
}
}
What this does is it looks through all of the checkboxes, and randomly selects blah checkboxes from boxes and checks them. blah is CA in your code.
Hope it helps!
Techcraft7

If you want to check exactly 60% of the rows (or the closest that rounding errors will let you get), you should sort the rows randomly then take the first 60% of them.
For example:
var r = new Random();
var checkboxes = this.Controls.OfType<CheckBox>();
float totalBoxes = checkboxes.Count();
var targetCount = (int)(totalBoxes * 0.60F);
var targetItems = checkboxes
.OrderBy( c => r.Next() ) //Sort randomly
.TakeWhile( (c,i) => i <= targetCount ); //take the first 60%
foreach (var c in targetItems) c.Checked = true;

Related

How can i take the values from texboxes by the name of it

I want the following code to give me the exact number of S values from the textboxes named : Box1_1 , Box1_2 , Box1_3, Box1_4, Box1_5 ...
But when i try to see the value it's always blank. What can i do ?
for (int i = 1; i <= 7; i++){
for (int j = 1; j <= 10; j++){
string box = "Box" + i.ToString() + "_" + j.ToString();
TextBox nameBox = new TextBox();
nameBox.Name = box;
if(string.Compare(nameBox.Text, "S")==0){
numberS++;
}
}
}
This is a cheeky little one-liner using Linq (split over multiple lines for clarity):
var textBoxes = this.Controls
.OfType<TextBox>() // controls that are TexteBoxes
.Where(t => t.Name.StartsWith("Box") && t.Text.StartsWith("S"))
.ToList();
int numberS = textBoxes.Count();
We get all TextBox controls using OfType<TextBox>()
This assumes the name of the TextBoxes you're interested in start with "Box". The corresponding Linq is Where(t => t.Name.StartsWith("Box")).
It looks like you're only interested in the TextBoxes that have a value that starts with "S". The corresponding linq is Where(t => t.Text.StartsWith("S")). I have combined these in a single Where.
Then we get the count: .Count()
If you want the count of textboxes that contain S (not just start with S) then use t.Text.Contains("S") in the Where clause instead.
If you want to get the TextBox names (Box1_1, Box1_2, etc) then you can use Select which will take the Name property from each TextBox and return a List<string>
var txtNames = this.Controls
.OfType<TextBox>() // controls that are TexteBoxes
.Where(t => t.Name.StartsWith("Box") && t.Text.StartsWith("S"))
.Select(t => t.Name) // select textbox names
.ToList();
txtNames is a List<string> containing the textbox names which start with S.
First of all, you need a collection of your TextBox'es or scrap them from your window. Example of how to do the second is here.
Here is your code that I modified:
public int CountS()
{
var numberS = 0;
for (int i = 1; i <= 7; i++)
{
for (int j = 1; j <= 10; j++)
{
string box = "Box" + i.ToString() + "_" + j.ToString();
TextBox nameBox
= UIHelper.FindChild<TextBox>(Application.Current.MainWindow, box); //using example linked above
//= textBoxes.First(tbx => tbx.Name == box); //if you got collection of your textboxes
numberS += nameBox.Text.Count(c => c == 'S'); //if you wont also count a small "s" add .ToUpper() before .Count
}
}
return numberS;
}

C# Loop through List of names and display names on a different label each time it loops

I am creating this Random Draw application. For example, User enters in 6 names, they then hit the randomize button and it displays the names randomly in labels beside each other. So for example name at index[0] will play name at index[3] and so on. The problem I am having is I'm not sure how to loop through and display each name on a different label. Is there a way to count my labels and loop through that way? Here is my code for looping through the names in the List and randomly picking one to display on the first label.
for(int i = 0; i < names.Count; i++)
{
Random rand = new Random();
int index = rand.Next(names.Count);
var name = names[index];
lblFirstName.Text = name;
lblFirstName.Visible = true;
names.RemoveAt(index);
}
As you can see the name will always be displayed on lblFirstName. I have 5 more labels named lblSecondName etc..
Use a While instead of a For
Put your labels on the same control (ex. Panel1)
List<string> labels = new List<string>() { "lblFirstName", "lblSecondName" , "lblThirdName" , .......... };
while (names.Count > 0) {
Random rand = new Random();
int index = rand.Next(names.Count);
var name = names[index];
names.RemoveAt(index);
index = rand.Next(labels.Count);
//WebForms
Panel1.FindControl(labels[index]).Text = name;
Panel1.FindControl(labels[index]).Visible = true;
//WinForms
Panel1.Controls(labels[index]).Text = name;
Panel1.Controls(labels[index]).Visible = true;
labels.RemoveAt(index);
}
var firstNames = new [] { lblFirstName1, lblFirstName2 , lblFirstName3 , .......... };
for(int i = 0; i < names.Count; i++)
{
Random rand = new Random();
int index = rand.Next(names.Count);
var name = names[index];
firstNames[i].Text = name;
firstNames[i].Visible = true;
names.RemoveAt(index);
}

Filling a dictionary with numbers from textbox and with the textboxes as keys

I'm writing a code where I want to get the numbers from multiple TextBox controls into a collection. Sort it, then change the background color of the textboxes containing the top 3 highest value. This is the dictionary
Dictionary<System.Windows.Forms.TextBox, string> all_cycles = new Dictionary<System.Windows.Forms.TextBox, string>(10);
for (var i = 1; i < 5; i++)
{
all_cycles.Add(((System.Windows.Forms.TextBox)this.Controls.Find("txtendc" + Convert.ToString(i), true)[0]),this.Text);
}
I know that with "this.text" I won't get the textboxes values so that's why I'm asking.
I also tried creating an array which only contains the values of the textboxes which I then use to fill the dictionary. But it always drops an Index was outside the bounds of the array. Or Index was out of range exception. This drops the out of range exception:
List<System.Windows.Forms.TextBox> txtendc = new List<System.Windows.Forms.TextBox>(10);
for (var i = 1; i < 5; i++)
{
txtendc.Add((System.Windows.Forms.TextBox)this.Controls.Find("txtendc" + Convert.ToString(i), true)[0]);
}
int[] endc_content = new int[10];
for (var i = 1;i < 5; i++)
{
endc_content[i]= int.Parse(txtendc[i].Text);
}
I don't have any problem with the coloring, just filling up the dictionary. If you have a better solution than the dictionary collection please tell me.
Thanks
EDIT: This whole code is inside a timer tick event if it matters anything
I would create a list of all of your TextBoxes in code behind when you instantiate your class. Then you could use Linq to get the top 3. Remember that you will need to confirm that all of the textboxes actually contain numbers - ensure that your program doesn't crash if you enter text into one of them. If all of the TextBoxes in the form will be holding these numbers, you could do something like this to validate and sort in one method (not tested):
private List<TextBox> myTextBoxes { get; set; }
public Form1()
{
InitializeComponent();
foreach (Control c in this.Controls)
{
if (c.GetType() == typeof(TextBox))
myTextBoxes.Add((TextBox)c);
}
}
private IEnumerable<TextBox> getTop3()
{
return myTextBoxes.Where(tb => tb.Text.AsEnumerable().All(char.IsDigit)).Select(tb => tb).OrderByDescending(tb => Double.Parse(tb.Text)).Take(3);
}
The first step of the Linq query converts the text to an enumerable of char and ensures that all characters contain digits (instead of letters). The second selects these textboxes. The third parses them into doubles and compares them, highest number first. The last takes the first three in the list (the textboxes containing the highest 3 numbers)
EDIT: Based on your comments, the code could be simplified to:
public Form1()
{
InitializeComponent();
}
private IEnumerable<TextBox> getTop3(string textboxPrefix)
{
List<TextBox> textBoxesToSort = new List<TextBox>();
foreach (Control c in this.Controls)
if (c.GetType() == typeof(TextBox) && c.Name.StartsWith(textboxPrefix))
textBoxesToSort.Add((TextBox)c);
return textBoxesToSort.OrderByDescending(tb => Double.Parse(tb.Text)).Take(3);
}
You can sort those TextBox controls based on values and then select top 3 from the list:
var result = this.Controls.OfType<TextBox>().Select(x =>
{
try { return new { Key = x, Value = Convert.ToInt32(x.Text) }; }
catch { return null; }
})
.Where(x=>x!=null)
.OrderByDescending(x => x.Value)
.Take(3)
.ToDictionary(x => x.Key, x => x.Value);
To test the result, show a message box containing values:
MessageBox.Show(string.Join("\n",
result.Select((x, i) => string.Format("{0}:{1}", i+1, x.Value))));
Above example will be applied on any list of TextBox controls and just for example I used all TextBox controls of the form.
Please try this, hope it helps:
List<System.Windows.Forms.TextBox> all_cycles = new List<System.Windows.Forms.TextBox>(10);
int[] indexOfTextBox = new int[3];
foreach(var cycle in all_cycles)
{
int value = Convert.ToInt16(cycle.Text);
if (value > indexOfTextBox[0])
{
indexOfTextBox[0] = value;
}
else if (value > indexOfTextBox[1])
{
indexOfTextBox[1] = value;
}
else if (value > indexOfTextBox[2])
{
indexOfTextBox[2] = value;
}
}
all_cycles[indexOfTextBox[0]].BackColor = ConsoleColor.Red;
all_cycles[indexOfTextBox[1]].BackColor = ConsoleColor.Blue;
all_cycles[indexOfTextBox[2]].BackColor = ConsoleColor.Green;

How can I check if column value same on every row on GridView?

I have a grid view with 10 rows.
After clicking on a button I would like to check and make sure each cell value are the same or not under the firstname column of gridview.
If all the cell values are same then call the changeCellValues() method. If any cell value is different then MessageBox.Show("You cant use your method");
private void button1_Click(object sender, EventArgs e)
{
string x;
string y;
x = dataGridView1.Rows[0].Cells[1].Value.ToString();
for (int i = 0; i < 11; i++)
{
y = dataGridView1.Rows[i].Cells[1].Value.ToString();
if (x == y) continue;
MessageBox.Show("You cant use your method");
}
}
How can I check if column value same on every row on GridView?
If you have 10 rows, change i < 11 to i < 10 and start i from 1 because you already get the first row's value and store it into x.Your way seems correct but instead of displaying the messagebox inside of the loop, you can use something like this:
x = dataGridView1.Rows[0].Cells[1].Value.ToString();
bool control = true;
for (int i = 1; i < 10; i++)
{
y = dataGridView1.Rows[i].Cells[1].Value.ToString();
if (x != y) { control = false; break; }
}
if(!control) MessageBox.Show("You cant use your method");
else changeCellValues();
Alternative using LINQ... grab everything in the column "firstname", remove duplicates using Distinct, and then count the number of unique names. (If you have more than 1 unique name, they're not all the same.)
var isSameName = dataGridView1.Rows.Cast<DataGridViewRow>()
.Select(x => Convert.ToString(x.Cells["firstname"].Value))
.Distinct().Count() == 1;
if (!isSameName)
{
MessageBox.Show("You cant use your method");
return;
}
changeCellValues();

Enable and Disable ToolStripMenu entries in C#?

I have a Form that contains a Menu with two entries, which are Menu and Tools. The two Menues have some SubMenus.
Now i have a TextBox called txtSelect and a Button called btnVisible, if I enter 1,2 in the TextBox, the SubMenus in the Menu should not be visible. I written the following code, bit it is Hard-written.
ToolStripMenuItem[] mstrip = new ToolStripMenuItem[] { msO1, msO2, msO3, msP1, msP2, msP3 };
if (txtSelect.Text.Length > 2)
{
string word = txtSelect.Text;
string[] splt = word.Split(',');
for (int x = 0; x < mstrip.Length; x++)
mstrip[x].Visible = true;
for (int x = 0; x < splt.Length; x++)
{
int y = Convert.ToInt32(splt[x].ToString()) - 1;
if (y >= 0 && y < mstrip.Length)
mstrip[y].Visible = false;
textBox1.AppendText(mstrip[y].Text);
textBox2.AppendText(mstrip[y].OwnerItem.Text);
}
}
I want to use foreach loop instead in a Button Click Event and have attempted with the following, however the result is not the same as with the code above.
foreach (ToolStripMenuItem mnItem in msMenus.Items)
{
MessageBox.Show(mnItem.Text);
for (int i = 0; i < mnItem.DropDown.Items.Count; i++)
{
MessageBox.Show(mnItem.DropDown.Items[i].Text);
mnItem.DropDown.Items[i].Visible = true;
}
}
Well, may be you want something like :
List<Int32> lstindex = new List<Int32>();
String[] splt = txtSelect.Text.Split(',');
// initialize list of indexed for textbox
foreach (String str in splt)
{
lstindex.Add(Convert.ToInt32(str) - 1);
}
// for each menu
foreach (ToolStripMenuItem mnItem in msMenus.Items)
{
// for each menu item
foreach (ToolStripItem item in mnItem.DropDown.Items)
{
// if index of item is in the list of indexed, set visible to false, otherwise to true
item.Visible = lstindex.Contains(mnItem.DropDown.Items.IndexOf(item)) ? false : true;
}
}

Categories

Resources