How to populate (mark checked) a checkedListBox with a StringCollection - c#

I have a checkedListBox with 10 Items in my Collection on my windows form. Using C# VS210.
I am looking for a simple way to mark as checked only 2 of the items from my checkedListBox by using values stored in the Settings.Settings file, (stored as System.Collections.Specialized.StringCollection). I have not been able to find this example out there, I know I am supposed to use the CheckedListBox.CheckedItems Property somehow, but haven't found an example.
private void frmUserConfig_Load(object sender, EventArgs e)
{
foreach (string item in Properties.Settings.Default.checkedListBoxSystem)
{
checkedListBoxSystem.SetItemCheckState(item, CheckState.Checked);
}
}

How about using an Extension method?
static class CheckedListBoxHelper
{
public static void SetChecked(this CheckedListBox list, string value)
{
for (int i = 0; i < list.Items.Count; i++)
{
if (list.Items[i].Equals(value))
{
list.SetItemChecked(i, true);
break;
}
}
}
}
And slightly change the logic in your load event, like this:
private void frmUserConfig_Load(object sender, EventArgs e)
{
foreach (string item in Properties.Settings.Default.checkedListBoxSystem)
{
checkedListBoxSystem.SetChecked(item);
}
}

The first parameter of SetItemCheckState takes an index (int). Try to get the index of the item you want to check, and then use SetItemCheckState with the index to check it.

Related

How to filter a specific record from BindingList c#

I have a bindinglist and after populating it, the list will be bind to a listbox.
private BindingList<VersionControlLabel> allTfsLabelList = new BindingList<VersionControlLabel>();
Versioncontrollabel class contains Name,version no, modified date etc..
Current implementation is when loading the form all the versions are load into the listbox then we have go through every item to find the specific one. Instead I want to add a textbox and when I type I want to show the record which has a exesiting word in textbox.
if user type the version number continuously the listbox should show the matching record
As enumrator properties are not available when I use the linq. How to do this?
I implemented something like this. But its not working. its not linq
private void txtSearchLabel_KeyUp(object sender, KeyEventArgs e)
{
if (!string.IsNullOrEmpty(txtSearchLabel.Text))
{
string text = txtSearchLabel.Text;
foreach (VersionControlLabel part in allTfsLabelList)
{
if(part.LabelId.ToString().Contains(text))
{
lstLabels.DataSource = part;
}
else
{
lstLabels.DataSource = allTfsLabelList;
}
}
}
}
If you want to just do ad hoc filtering then you can do something like this:
private List<string> allItems = new List<string>();
private void DisplayFilteredList()
{
var searchText = textBox1.Text.Trim();
listBox1.DataSource = searchText.Length == 0
? allItems
: allItems.Where(s => s.Contains(searchText)).ToList();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
DisplayFilteredList();
}

Add and delete text to/from ListBox hosted in WinForm using C#

I am working on a simple application that to add/delete string/s into an array and show that in ListBox.
My code shows only the latest value that was typed into the textBox and
private void Add_Click(object sender, EventArgs e)
{
string add = textBox1.Text;
List<string> ls = new List<string>();
ls.Add(add);
String[] terms = ls.ToArray();
List.Items.Clear();
foreach (var item in terms)
{
List.Items.Add(item);
}
}
private void Delete_Click(object sender, EventArgs e)
{
}
This code makes no sense. You are adding one single item to a list, then convert it to an array (still containg one item) and finally loop through this array, which of course adds one item to the previously cleared listbox. Therefore your listbox will always contain one single item. Why not simply add the item directly?
private void Add_Click(object sender, EventArgs e)
{
List.Items.Add(textBox1.Text);
}
private void Delete_Click(object sender, EventArgs e)
{
List.Items.Clear();
}
Also clear the listbox in Delete_Click instead of Add_Click.
If you prefer to keep the items in a separate collection, use a List<string>, and assign it to the DataSource property of the listbox.
Whenever you want the listbox to be updated, assign it null, then re-assign the list.
private List<string> ls = new List<string>();
private void Add_Click(object sender, EventArgs e)
{
string add = textBox1.Text;
// Avoid adding same item twice
if (!ls.Contains(add)) {
ls.Add(add);
RefreshListBox();
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Delete the selected items.
// Delete in reverse order, otherwise the indices of not yet deleted items will change
// and not reflect the indices returned by SelectedIndices collection anymore.
for (int i = List.SelectedIndices.Count - 1; i >= 0; i--) {
ls.RemoveAt(List.SelectedIndices[i]);
}
RefreshListBox();
}
private void RefreshListBox()
{
List.DataSource = null;
List.DataSource = ls;
}
The problem with code is quite simple. Instead of adding new item to list your code creates new list with one added item only. I am trying to interpret functions of program and they seem to be:
Enter new text into top level text box.
If Add button is clicked your item goes on top of the list (if it's bottom see end of my answer).
If item(s) is selected in list and Delete is clicked selected item(s) is/are deleted.
To achieve this you should first insert text on top of the list by using Add_Click code, than delete selected items using Delete_Click code. There is additional code to guard against inserting empty or white space only strings plus trimming of leading and trailing white space.
private void Add_Click(object sender, EventArgs e)
{
// Since you do not want to add empty or null
// strings check for it and skip adding if check fails
if (!String.IsNullEmptyOrWhiteSpace(textBox1.Text)
{
// Good habit is to remove trailing and leading
// white space what Trim() method does
List.Items.Insert(0, textBox1.Text.Trim());
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Get all selected items indices first
var selectedIndices = List.SelectedIndices;
// Remove every selected item using it's index
foreach(int i in selectedIndices)
List.Items.RemoveAt(i);
}
To complete adding and deleting logic I would add Delete All button which would just call List.Items.Clear(). If you prefer to add text at the end just use Add method form #Olivier Jacot-Descombes answer.
You can use in C#:
private void Delete_Click(object sender, EventArgs e)
{
if(myList.Contains(textbox1.value))//if your list containt the delete value
{
myList.Remove(textbox1.value); //delete this value
}
else
{
//the list not containt this value
}
}
and you can use the same method for validate if a value exist when try to add
private void AddItem()
{
if (!String.IsNullEmptyOrWhiteSpace(textBox1.Text))
{
var newItem = textBox1.Text.Trim();
if (!List.Items.Contains(newItem))
{
List.Items.Add(newItem);
// Alternative if you want the item at the top of the list instead of the bottom
//List.Items.Insert(0, newItem);
//Prepare to enter another item
textBox1.Text = String.Empty;
textBox1.Focus();
}
}
}
private void Add_Click(object sender, EventArgs e)
{
AddItem();
}
Private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
AddItem();
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Remove every selected item using it's index
foreach(var item in List.SelectedItems)
{
List.Items.Remove(item);
}
}

update a list after deleting an item

i have a form that when i add a item it stores it within a list and adds it to a checklistbox
i have a button that deletes the item from the checklist box, but how would i get it so that when i delete it from the checklistbox it also deletes it within the list its been stored in
here is the code for the delete button
private void btnDelete_Click(object sender, EventArgs e)
{
for (int i = clbSummary.CheckedIndices.Count - 1; i >= 0; --i)
{
clbSummary.Items.RemoveAt(clbSummary.CheckedIndices[i]);
}
}
Why don't you do remove the item from the list within the btnDelete_Click method.
For example:
private void btnDelete_Click(object sender, EventArgs e)
{
for (int i = clbSummary.CheckedIndices.Count - 1; i >= 0; --i)
{
object item = clbSummary.Items[clbSummary.CheckedIndices[i]];
myList = myList.Remove(item);
clbSummary.Items.RemoveAt(clbSummary.CheckedIndices[i]);
}
}
I'm not sure if you can use the [] operator on Items, but this is to give you a general idea.
Set the checklistbox DataSource property to the list where you are storing the items. When you make any changes to the list, your checklistbox will update.

Collection was modified; enumeration may not execute error when removing a ListItem from a LIstBox

I have two ListBoxes, lstAvailableColors and lstSelectedColors. Between each listbox are two buttons, Add and Remove. When a color or colors is selected in lstAvailableColors and the Add button is clicked, I want to remove them from lstAvailableColors and display them in lstSelectedColors. Also, if colors are selected in lstSelectedColors and the Remove button is clicked, I want to remove the colors from lstSelectedColors and add them back to lstAvailableColors. When I do this, I get the following error when it removes the item:
Collection was modified; enumeration operation may not execute.
Here is the code for the Add Button and the Remove Button:
Add:
protected void btnAdd_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstAvailableColors.Items)
{
if (item.Selected)
{
lstSelectedColors.Items.Add(item);
lstAvailableColors.Items.Remove(item);
}
}
}
Remove:
protected void btnRemove_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstSelectedColors.Items)
{
if (item.Selected)
{
lstAvailableColors.Items.Add(item);
lstSelectedColors.Items.Remove(item);
}
}
}
It's not possible to modify a collection while you're enumerating it in .Net. You need to separate out your enumeration and remove code into different blocks. Here is a quick sample on how to do that in without LINQ
protected void btnAdd_Click(object sender, EventArgs e)
{
var selected = new List<ListItem>();
foreach (ListItem item in lstAvailableColors.Items)
{
if (item.Selected)
{
selected.Add(item);
lstSelectedColors.Items.Add(item);
}
}
foreach (ListItem item in selected)
{
lstAvailableColors.Items.Remove(item);
}
}
And here's a more concise version using LINQ
var selected = lstAvailableColors.Cast<ListItem>().Where(i => i.Selected).ToList();
selected.ForEach( x => { lstSelectedColors.Items.Add(x); });
selected.ForEach( x => { lstAvailableColors.Items.Remove(x);});
EDIT
The LINQ version works in two parts. The first part is the first line which finds the currently selected items and stores the value in a List<ListItem>. It's very important that the line contain the .ToList() call because that forces the query to execute immediately vs. being delayed executed.
The next two lines iterate through each value which is selected and remove or add it to the appropriate list. Because the selected list is already stored we are no longer enumerating the collection when we modify it.
You cannot modify an collection while you are using an Enumerator for this collection, what the for each statement does.
You have to loop over the data with a normal for loop and then you can modify the collection, but you must be careful to correctly update the current index if you insert or remove elements. If you just add or remove elements and don't insert some, iterating from the last element to the first will do.
protected void btnAdd_Click(object sender, EventArgs e)
{
for (Int32 i = lstAvailableColors.Items.Count; i >= 0; i--)
{
ListItem item = lstAvailableColors.Items[i];
if (item.Selected)
{
lstSelectedColors.Items.Add(item);
lstAvailableColors.Items.Remove(item);
}
}
}
You cannot modify a collection you are iterating on. In general, a good solution for this type of problem is to create an empty collection, and in your iterator, copy over all of the elements you do NOT want to remove; after the iteration is complete, replace the original collection with your new collection.
As the other answer mentioned, you can't remove items until you've completed the iteration. So perhaps something like this will be cleanest for you:
var itemsToRemove =
lstAvailableColors.Items.Cast<ListItem>().Where(i => i.IsSelected).ToArray();
foreach(ListItem item in itemsToRemove) lstAvailableColors.Remove(item);
You can't modify a collection while you're iterating over it. Either iterate over a copy or use for, iterate in reverse and remove as you go down.
Example on how to remove the selected Items. Here only the selected indices are taken and removed.
public void RemoveSelectedItems(ListBox listbox)
{
List<ListItem> items = GetSelectedItems(listbox);
foreach (var listItem in items)
{
listbox.Items.Remove(listItem);
}
}
public List<ListItem> GetSelectedItems(ListBox listbox)
{
int[] selectedIndices = listbox.GetSelectedIndices();
return selectedIndices.Select(index => listbox.Items[index]).ToList();
}
Maybe this is what you need
protected void btnAdd_Click(object sender, EventArgs e)
{
while(listBox1.SelectedIndex!=-1)
{
listBox1.Items.Remove(listBox1.SelectedItem);
}
}
This might help you;
To Remove:
protected void btnRemove_Click(object sender, EventArgs e)
{
{
for (int i = 0; i < lstAvailableColors.Items.Count; i++)
{
if(lstAvailableColors.Items[i].Selected)
lstAvailableColors.Items.RemoveAt(i);
}
}
}
The problem you face is that you can't modify the collection you itterate thru. You could solve this by using a single linq:
protected void btnAdd_Click(object sender, EventArgs e)
{
lstAvailableColors.Items.RemoveAll(ac => ac.Selected);
}
You can use this generic function to remove mulitple items form ObservableCollection ( I know that many are scared of Exceptions, but Exception is nothing but a dev tool)
public static void OCRemoveMultiple<T>(ref ObservableCollection<T> inputList, IList<T> toRemoveItems)
{
REITERATE:
{
try
{
while( inputList.Intersect<T>(toRemoveItems).Any())
{
var intersectionList = inputList.Intersect<T>(toRemoveItems);
foreach (var item in intersectionList)
{
inputList.Remove(item);
}
}
}
catch (Exception)
{
goto REITERATE;
}
}
}
Here is a test case (an example) how you can use it:
ObservableCollection<object> targetList = new ObservableCollection<object>();
targetList.Add("T1");
targetList.Add("T2");
targetList.Add("B3");
targetList.Add("B4");
targetList.Add("T5");
IList<object> toRemove = targetList.ToList().Where(k=>k.ToString().Contains("B")).ToList();
OCRemoveMultiple(ref targetList, toRemove);
targetList.ToList().ForEach(k => Console.WriteLine(k.ToString())); // Writes "T1", "T2" and "T5"

How to programmatically check an item in a CheckedListBox in C#?

I have a CheckedListBox, and I want to automatically tick one of the items in it.
The CheckedItems collection doesn't allow you to add things to it.
Any suggestions?
You need to call SetItemChecked with the relevant item.
The documentation for CheckedListBox.ObjectCollection has an example which checks every other item in a collection.
This is how you can select/tick or deselect/untick all of the items at once:
private void SelectAllCheckBoxes(bool CheckThem) {
for (int i = 0; i <= (checkedListBox1.Items.Count - 1); i++) {
if (CheckThem)
{
checkedListBox1.SetItemCheckState(i, CheckState.Checked);
}
else
{
checkedListBox1.SetItemCheckState(i, CheckState.Unchecked);
}
}
}
In my program I've used the following trick:
CheckedListBox.SetItemChecked(CheckedListBox.Items.IndexOf(Item),true);
How does things works:
SetItemChecked(int index, bool value) is method which sets the exact checked state at the specific item. You have to specify index of item You want to check (use IndexOf method, as an argument specify text of item) and checked state (true means item is checked, false unchecked).
This method runs through all items in CheckedListBox and checks (or unchecks) the one with specified index.
For example, a short piece of my code - FOREACH cycle runs through specified program names, and if the program is contained in CheckedLitBox (CLB...), checks it:
string[] ProgramNames = sel_item.SubItems[2].Text.Split(';');
foreach (string Program in ProgramNames)
{
if (edit_mux.CLB_ContainedPrograms.Items.Contains(Program))
edit_mux.CLB_ContainedPrograms.SetItemChecked(edit_mux.CLB_ContainedPrograms.Items.IndexOf(Program), true);
}
Suppose you want to check the item on clicking a button.
private void button1_Click(object sender, EventArgs e)
{
checkedListBox1.SetItemChecked(itemIndex, true);
}
Where itemIndex is the index of the item to be checked, it starts from 0.
Use:
string[] aa = new string[] {"adiii", "yaseen", "salman"};
foreach (string a in aa)
{
checkedListBox1.Items.Add(a);
}
Now code where you want to check all:
private void button5_Click(object sender, EventArgs e)
{
for(int a=0; a<checkedListBox1.Items.Count; a++)
checkedListBox1.SetItemChecked(a, true);
}
To uncheck all:
private void button_Click(object sender, EventArgs e)
{
for(int a=0; a<checkedListBox1.Items.Count; a++)
checkedListBox1.SetItemChecked(a, false);
}
I use an extension:
public static class CheckedListBoxExtension
{
public static void CheckAll(this CheckedListBox listbox)
{
Check(listbox, true);
}
public static void UncheckAll(this CheckedListBox listbox)
{
Check(listbox, false);
}
private static void Check(this CheckedListBox listbox, bool check)
{
Enumerable.Range(0, listbox.Items.Count).ToList().ForEach(x => listbox.SetItemChecked(x, check));
}
}

Categories

Resources