I'm making a program that has to count how many CheckBox controls are checked, only in a GroupBox.
I've tried a lot of different ways but I can't get it work.
How can this be made?
// This is one of the many things I tried...
public CheckBox rNum;
//This method is used on FormLoad.
public void CreateBoxes()
{
for (int i = 0; i < 36; i++)
{
rNum = new CheckBox();
rNum.Text = i.ToString();
//CheckBoxes added to flowLayoutPanel.
flw.Controls.Add(rNum);
}
}
public int count;
//This method is used on Button Click
public void CountIt()
{
foreach (CheckBox box in groupBox.Controls.OfType<CheckBox>())
{
if (box.Checked)
{
count++;
}
}
MessageBox.Show(count.ToString());
}
You can use a linq query like this:
var count = flw.Controls.OfType<CheckBox>().Count(x=>x.Checked);
It returns count of CheckBox controls in flw which are checked.
Based on your comments and the edits to your question, you need to be looking for your CheckBoxes in the FlowLayoutPanel to which you added them, not groupBox. Given that your FlowLayoutPanel is called flw, do the following:
public void CountIt()
{
foreach (CheckBox box in flw.Controls.OfType<CheckBox>())
{
if (box.Checked)
{
count++;
}
}
MessageBox.Show(count.ToString());
}
Note that I'm increasing the count only when the CheckBox is checked, which is now reflected in your question. Failing to do that check was a bug in your original code.
Related
I know how to set item to checked:
checkedListBox.SetItemChecked(index, true);
but i am having it called when i am opening form with parameter of int[] valueMembers so i want to check every value member that is = to this parameter to checked. Here is what i have tried:
public NovaPoruka(int[] primalacID)
{
InitializeComponent();
foreach(CheckedListBox o in checkedListBox1.Items)
{
if(primalacID.Contains(Convert.ToInt32(o.SelectedValue)))
{
o.SetItemChecked(o.SelectedIndex, true);
}
}
}
Edit:
I haven't seen that i didn't initialize checkedListBox before doing this so it wasn't dropping error but now when i made that i drops me error at CheckedListBox o in checkedListBox1.Items so i made little change but still do not know how to get index of current item that is inside foreach loop. Here is changed code:
foreach(Int_String o in checkedListBox1.Items)
{
if(primalacID.Contains(Convert.ToInt32(o._int)))
{
checkedListBox1.SetItemChecked(checkedListBox1.SelectedIndex, true);
}
}
current way of getting selected index returns me -1
I have done it. Here is final code:
for(int i = 0; i < checkedListBox1.Items.Count; i++)
{
Int_String s = checkedListBox1.Items[i] as Int_String;
if(primalacID.Contains(s._int))
{
checkedListBox1.SetItemChecked(i, true);
}
}
I'm still new at coding. I'm making a calculator but I also want a lot of other things in it. like a conversion calculator, cook book, and kanji radical dictionary in c# WindowsFormsApplication I want to change from one to the next using a comboBox so I was going to make a array with all the control I wish to hide/show
string[] numList = {"button0","button1","button2", "button3"};//this will have all number and .
for (int i = 0; i < numList.Length; i++)
{
numList[i].Hide();
}
But it tell me there no definition for 'Hide' but when I switch numList[i] to button0 it work but I don't wish to wright the same 11 control for every time i add something to the comboBox anyway to fixes this or any other method
If you want to hide all Buttons then try this:
foreach (Button control in Controls.OfType<Button>())
{
(control).Hide();
}
This iterate through all Buttons of the form and hide them. But if you want to just hide a specific buttons then you can set the Tag property of that buttons to something like OP then to hide only that Buttons:
foreach (Button control in Controls.OfType<Button>())
{
if (control.Tag.ToString() == "OP")
{
(control).Hide();
}
}
Or with linq:
foreach (Button control in Controls.OfType<Button>().Where(control => control.Tag.ToString() == "OP"))
{
(control).Hide();
}
try below code
private void btnHide_Click(object sender, EventArgs e)
{
string[] buttonList = { "button1", "button2", "button3" };
for (int i = 0; i < buttonList.Length; i++)
{
Control[] ctrl = this.Controls.Find(buttonList[i], true);
((Button)ctrl[0]).Visible = false;
}
}
You are keeping a list of strings, you should actually add the buttons in to the list in order to have the Hide method visible
Control[] numList = {button0, button1, button2, button3 };
I've been searching for about an hour already and couldn't find a best solution.
I am migrating from VB.NET to C# Forms and to C# WPF.
Never mind that...
so I use this code for C# forms and it works, but not in C# WPF
if (ListView1.SelectedItems.Count > 0)
{
for (lcount = 0; lcount <= ListView1.Items.Count - 1; lcount++)
{
if (ListView1.Items[lcount].Selected == true)
{
var2 = lcount;
break;
}
}
}
this is the way I want to get the index of the item clicked in listbox.
I have the error in .SELECTED
please help.
You can get SelectedIndex from listView. No need to traverse over all items because as per your code you seems to be interested in index of any selected item.
var2 = ListView1.SelectedIndex;
OR
simply this will work if interested in only first index:
if (lst.SelectedItems.Count > 0)
{
var2 = lst.Items.IndexOf(lst.SelectedItems[0]);
}
If you are using the .NET Compact Framework, SelectedIndex is not supported. For a general solution, I prefer SelectedIndices:
ListView.SelectedIndexCollection indices = lst.SelectedIndices;
if (indices.Count > 0)
{
// Do something with indices[0]
}
For Visual Studio 2015, SelectedIndex does not seem to be available. Instead, you can use SelectedIndices[x] where x=0 will give you the first selected item:
listView.SelectedIndices[0]
You can also set the MultipleSelect property to false to only allow one item to be selected at a time.
It can return NULL. Also the SelectedIndexChanged event can be FIRED TWICE. And the first time, there nothing selected yet.
So the only safe way to find it is like this:
private void lv1_SelectedIndexChanged(object sender, EventArgs e)
{
if (lv1.FocusedItem == null) return;
int p = lv1.FocusedItem.Index;
... now int p has the correct value...
sColl.Clear();
string item = String.Empty;
if (listView1.SelectedItems.Count > 0) {
for (int i = 0; i < listView1.SelectedItems.Count; i++) {
if (listView1.SelectedItems[i].Selected) {
int i2 = listView1.SelectedItems[i].Index;
item = listView1.Items[i2].Text;
sColl.Add(item);
}
}
}
listView1.SelectedItems.Clear();
foreach (var itemS in sColl)
{
string items = itemS;
}
sColl.Clear();
listView1.SelectedItems.Clear();
Why don't bring back the SelectedIndex ? Add this extension after your current namespace.
public static class Extension
{
public static int SelectedIndex(this ListView listView)
{
if (listView.SelectedIndices.Count > 0)
return listView.SelectedIndices[0];
else
return 0;
}
}
Encapsulate this class in a namespace called Extensions and then add this inside your projects namespace to use the extension.
using Extensions;
Then simply use like this
private void ListView1_SelectedIndexChanged(object sender, EventArgs e)
{
int selectionindex = ListView1.SelectedIndex();
ListViewItem seletedItem = ListView1.Items[selectionindex];
}
P.S.
The extension method should have returned -1 on Else, but as long as you're using it from the SelectedIndexChanged event, you're fine as it won't get fired if there are no items.
This is by design, as the SelectedIndexChanged event gets fired twice. Once to deselect the initial item, then to select the new one.
Proper way is to return -1 and check for negative numer.
This is also why someone here got and ArgumentOutOfRange Exception.
I have a method that adds items to my listbox called refreshInterface which is called as soon as the programe starts, adding names of homeforms in the listbox using the FormItems class, here is the rereshInterface method below
public void refreshInterface()
{
//int number = 0;
foreach (DataSet1.xspGetAnalysisUsageTypesRow homeForms in myDataSet.xspGetAnalysisUsageTypes)
{
var forms = new FormItems(homeForms);
listBox1.Items.Add(forms);
}
}
The FormItems class is this below
public class FormItems
{
public DataSet1.xspGetAnalysisUsageTypesRow types { get; set; }
public FormItems(DataSet1.xspGetAnalysisUsageTypesRow usageTypes)
{
types = usageTypes;
}
public override string ToString()
{
// returns the rows that are relating to types.xlib_ID
var libtyps = types.GetxAnalysisUsageRows();
var cnt = 0;
foreach (DataSet1.xAnalysisUsageRow ty in libtyps)
{
//returns true if ty is null
bool typeNull = ty.Isxanu_DefaultNull();
// if its false, if xanu_Default is set
if (!typeNull)
{
cnt += 1;
}
}
var ret = String.Format("set {0} [Set: {1}]", types.xlib_Desc, cnt);
//return this.types.xlib_Desc;
return ret;
}
}
Each listbox (the listbox is on the left of the homeform) item has a number of reports that can be added to it, so for instance, i select an homeform from my listbox, there are 12 textboxes on the right hand side and each textbox has a pair of buttons which are Browse and Clear. If I click on the browse button a new form appears, and i select a report from that form and add it to a particular textbox, the count for that homeform should update, and i clear a textbox for a particular homeform, the count should also update.
At the moment when i debug the application, it shows me the count of each Homeform depending on the amount of reports added to the homeform, but while the programe is running, if i add a new report to a homeform, the count does not update until i restart the debug session. I was told about using a Databinding method but not sure of how i could use it here
How do i ge my listbox item to update ?
You should probably look into binding. Here is a good place to start:
http://www.codeproject.com/Articles/140621/WPF-Tutorial-Concept-Binding
If you want a GUI to respond to data changes then binding is your best friend.
You should bind List Box component source to Observable Collection, every update you do to Observable Collection will update List Box data.
Might not be exact but should give you an idea.
public void refreshInterface()
{
Dictionary<int,string> items = new Dictionary<int,string>();
//int number = 0;
foreach (DataSet1.xspGetAnalysisUsageTypesRow homeForms in myDataSet.xspGetAnalysisUsageTypes)
{
var formitem = new FormItems(homeForms);
items.Add(formitem.someprop, formitem.toString());
}
listbox.DataSource = items;
listbox.DisplayMember = "Value";
listbox.ValueMember = "Key";
}
I tried to find the answer by googling but no luck.
I designed form with panel containing textboxes so I can iterate through its controls
and save every textbox in an array (so I can iterate the array when I want to),
the thing is I couldn't find which property the panel knows how to arrange the order to iterate the controls inside it, which is the first, second,etc..
I thought maybe it's by tag, but when I changed them to my likings it didn't change anything.
so I wonder - how can you tell the panel iteration to go through the controls as you prefer?
which property do you need change?
private void CreateTxtArr()
{
txts = new TextBox[8];
for (int i = 0; i < pnlTxt.Controls.Count; i++)
txts[i] = (TextBox)pnlTxt.Controls[i];
}
You can use is operator to check if the child control of panel is TextBox
private void CreateTxtArr()
{
txts = new TextBox[8];
for (int i = 0; i < pnlTxt.Controls.Count; i++)
if( pnlTxt.Controls[i] is TextBox)
txts[i] = (TextBox)pnlTxt.Controls[i];
}
If you can use .Net 3.5 or higher, you can do it pretty easly with Linq:
private void CreateTxtArray()
{
// txts is an Array of TextBox
var txts = (from Control ctrl in pnlTxt.Controls
where ctrl is TextBox
select ctrl as TextBox).ToArray();
}
Is a simpler way to iterate, in all cases
EDIT: this is an old answer I had forgotten about, below there is an even simpler way to do that
private void CreateTxtArray()
{
// txts is an Array of TextBox
var txts = pnlTxt.Controls.OfType<TextBox>().ToArray();
}