I want to check about 3000 item in listview. This is a bit of code :
foreach (ListViewItem item in this.lvItem.Items)
{
item.Checked = !item.Checked;
}
But listview is very slow when item is checked. Please give me some ideas to solve this problem? Thanks.
I had the same problem but I found why.
I had an "ItemChecked" event handler attached to my listView that was doing some heavy stuff.
I removed the eventHandler and it solved my problem.
Try removing any "ItemChecked" eventhandler and see if the speed is better.
You need to call BeginUpdate before the loop and EndUpdate after the loop:
listView1.BeginUpdate();
foreach (ListViewItem item in listView1.Items)
item.Checked = true;
listView1.EndUpdate();
Calling BeginUpdate prevents the control from drawing until the EndUpdate method is called.
I heard a rumor that for large list items a for loop will work faster than a foreach loop
try
for(int i = 0; i = < this.1vItem.Items.Count; i++)
{
//Stuff
}
I also don't think it's wise to expect a user to click 3000 items. But something I did recently, when adding the items, knowing that there would never be many and by default they should be checked, is check the items before adding them to the list.
Something like this:
foreach (Recipient recipient in recipients)
{
var item = new ListViewItem(recipient.FirstName + " " + recipient.LastName);
item.Tag = recipient;
item.Checked = true;
lvRicipients.Items.Add(item);
}
Will something like this work for you? ...when checked, add the items to a Dictionary ...when unchecked, remove from the Dictionary. Not tested code but wondering if you could do something like this:
Dictionary<String, ListViewItem> Dic = listView.Items
.Cast<ListViewItem>()
.ToDictionary(x => x.Text, x => x.SubItems[0].Checked);
You asked how to better go about it. What I am saying is on your Check Event you will want to add items to your list view. I doubt that a user will actually check all 3000, so change your code to decide how you would want to handle checked items, the example that I have given you uses Lambda expression. If not familiar, then please alter your question to reflect what it is that you actually need and/or want...
for (int i = 0; i <= listView1.Items.Count - 1; i++)
{
if (!listView1.Items[i].Checked)
listView1.Items[i].Checked = true;
}
Related
I am having trouble with removing an item from a list in c#. My current code is below:
for (int i = current.Count - 1; i >= 0; i--)
{
foreach (ListItem li in sp_list.Items)
{
if (li.Text == current[i].uname)
{
current.RemoveAt(i);
}
}
}
The aim of the code is to compare the existing items in a list box with newly added items so I know which items have just been added. So currently I am getting the current list box items from the database (they are stored here, it is a databound list box), entering these into a list and for each of the list items, comparing them with the items in a list box and if they match, remove the item from the list.
Therefore, in the end, if I add two new entries, the list should only be storing the two newly added values.
The code does not work as the first item is removed fine, but then, the value of i is greater than current.count - and therefore I get an out of range exception!
Could someone help me with this issue? Apologies about the confusing question, it's hard to explain! Thanks
You can do it with Linq. Not sure if casting to ListItem needed (you can remove it)
current.RemoveAll(x => sp_list.Items.Cast<ListItem>()
.Any(li => li.Text == x.uname));
Once you've found the matching value, and removed it from the list, you want to break out of the inner loop to check the next item.
if (li.Text == current[i].uname)
{
current.RemoveAt(i);
break;
}
Your nesting is wrong, I think you wanted,
foreach (ListItem li in sp_list.Items)
{
for (int i = current.Count - 1; i >= 0; i--)
{
if (li.Text == current[i].uname)
{
current.RemoveAt(i);
}
}
}
alternatively, use linq,
// For lookup performance.
var items = new HashSet(sp_list.Items.Select(i => i.text));
current = current.Where(c => !items.Contains(c.uname)).ToList();
How about this:
foreach (ListItem li in sp_list.Items) {
if (current.Contains(li.Text)) {
current.Remove(li.Text);
}
}
Put a break statement after the RemoveAt so you don't remove that item again.
you can travel the list in reverse order and remove items using RemoveAt(i).
also for efficiency purposes you may want to put the ListItem texts in a Set so you can don't have to loop though the sp_list.Items for each of your current items.
IList<object> itemsSelected = MyGrid.SelectedItems;
foreach (object itemSelected in itemsSelected)
{
MyGrid.SelectedItems.Remove(itemSelected);
}
I try remove selected items from a GridView but not all selected items are removed.
Could someone help me?
object[] itemsSelected = MyGrid.SelectedItems.ToArray<object>();
foreach (object item in itemsSelected)
{
MyGrid.Items.Remove(item);
}
I had the exact problem as well. I wrote something like this but it didn't delete all items too, just some of them :
foreach(var item in MyGridView.SelectedItems)
{
MyGridView.Items.Remove(item);
}
But write this which will delete all your selected items for sure :
while (YourGridView.SelectedItems.Count != 0)
{
YourGridView.Items.Remove(YouGridView.SelectedItem);
}
there isn't exception, when you use foreach with SelectedItems? When you remove item, SelectedItems array is modified and foreach throws an exception. (Though I've tried on ListBox control). Try to use for-operator and remove items from last to first by index.
Based on your answers in the comments, I assume you are working on a C# winforms application.
Is it possible that what you are actualy using is a ListBox and not a GridView?
If that is so, you should use the ClearSelected() method which unselects all items in the ListBox.
I have a listview with few items. I am using foreach loop to check if there is a match. The code I am using looks like this:
foreach (ListViewItem test in listView1.Items)
{
if (test.SubItems[1].ToString() == item.SubItems[1].ToString())
{
test.Tag = item.Tag;
}
}
What I am trying to do is, check the 2nd index and if there is a match replace the old item 'test' with the new one 'item'.
Apparently there is no change in the listview. Is the way I am replacing the object wrong?
you can clone the item and assign directly to the list view item. but you need to change foreach loop to for loop.
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].SubItems[1].ToString() == item.SubItems[1].ToString())
{
listView1.Items[i] = (ListViewItem)item.Clone();
}
}
You have updated the Tag only. You need to change test.SubItems[0], test.SubItems[1],... to see the changes.
Or you could remove old item and insert new item by using listView1.Items.Remove(...) or listView1.Items.RemoveAt(...) and listView1.Items.Insert(...). But if you need to pay account of performance you should use the first algorithm (changing test.SubItems[i]).
Hi there I have searched for a while now and can't seem to find a solution to my problem, I have tried multiple methods to select multiple items in my listbox through code however none have worked, The best result I got was 1 selected item in my listbox.
Basically I want to select multiple items of the same value.
below is my code, sorry if I seem newbie but I am new to programming and still learning basic stuff.
foreach (string p in listBox1.Items)
{
if (p == searchstring)
{
index = listBox1.Items.IndexOf(p);
listBox1.SetSelected(index,true);
}
}
So as you can see I am trying to tell the program to loop through all the items in my listbox, and for every item that equals "searchstring" get the index and set it as selected.
However all this code does is select the first item in the list that equals "searchstring" makes it selected and stops, it doesn't iterate through all the "searchstring" items.
As suggested in the comment, you should set SelectionMode to either MulitSimple or MultiExpanded depending on your needs, but you also need to use for or while loop instead offoreach, because foreach loop doesn't allow the collection to be changed during iterations. Therefore, even setting this Property won't make your code run and you will get the exception. Try this:
for(int i = 0; i<listBox1.Items.Count;i++)
{
string p = listBox1.Items[i].ToString();
if (p == searchstring)
{
listBox1.SetSelected(i, true);
}
}
You can set SelectionMode either in the Properties window when using designer or in, for instance, constructor of your Form using this code:
listBox1.SelectionMode = System.Windows.Forms.SelectionMode.MultiSimple;
I have this code:
foreach (var item in ListView1.Items)
{
ListView1.Items.Remove(item);
ListView21.Items.Add(item);
}
the loop stops at half of the items?
Any idea?
EDIT
Well, maybe it's my mistake, I need to clarify that this is UltraListView control from Infrajistics, where I can't add item to another list unless I remove it or clone it from the original list.
But thanks, most of the comments regarding do not modify the list within the loop were correct, so this code works:
foreach (var item in listView1.Items)
{
var i = item.Clone(true);
listView2.Items.Add(i);
}
listView1.Items.Clear();
Thanks,
You cannot modify iterated collection, it should die with exception (or in undefined behavior).
Try making a copy of the array:
foreach (var item in ListView1.Items.ToArray())
{
ListView1.Items.Remove(item);
ListView21.Items.Add(item);
}
EDIT:
in fact, your example code can be achieved by writing:
ListView21.Items.AddRange(ListView1.Items);
ListView1.Items.Clear();
(which in fact isn't EXACTLY what you are doing, but gives the same result and I think it won't bother you having the same content in both listviews for a moment). The latter is supported since .NET2.0, first solution requires linq, and therefore .NET3.5.
You are modifying the collection you are looping through. Try using a for statement from top to bottom (from the item with the highest index to 0).
for (int i = ListView1.Items.Count - 1; i >= 0; i--)
{
var item = ListView1.Items[i];
ListView1.Items.Remove(item);
ListView21.Items.Insert(0, item);
}
It will cause a runtime exception, complaining that you cannot modify the collection while iterating through it. You have to use for loop instead.
for(int index = Items.Count; index > 0; index--)
{
.......
// use Add and RemoveAt
}
EDIT : As mentioned by others. If you just need to move items from one collection to the other. AddRange and Clear will be better.
Do you get any exception or error message? Looping in a collection and remove items from the same collection is always a bad idea.
This looks like the WinForms list view control, so:
ListViewItem[] items = ListView1.Items.ToArray();
ListView1.Items.Clear();
ListView21.Items.AddRange(items);
Why just not CopyTo() to new list and then Clear() items?
You are looping through all items, removing all of them, then adding them to another list. As others have commented, you cannot remove items from a list in a for-each. Why not looping through all items to add them to your other list, and then remove them all in one go?
foreach (var item in ListView1.Items)
{
ListView21.Items.Add(item);
}
ListView1.Items.Clear(); // remove all
PS: is this an ASP.NET listview or a WinForms listview?
That's because you're changing the collection inside the loop.
Use a normal for loop as follows:
for(int i=0; i < ListView1.Items.Count-1; i++)
{
ListView21.Items.Add(ListView1.Items[i]);
ListView1.Items.RemoveAt(i);
}