Why does SubItems.Clear () also remove the Name attribute?

I use WinForms ListView in verbose mode (.NET 4.0, running on Windows 7), and I have a function that should clear subelements in a specific element. Unfortunately, when I do this, it also clears the name:

item.Name = "TESTNAME"; item.SubItems.Clear(); MessageBox.Show(item.Name); //shows nothing 

In the debugger, I tracked it before that, and I looked at the documentation on MSDN , and it is useless,

Clear: removes all subitems and the parent ListViewItem from the collection.

In addition, ListViewItem still exists, because later in the function I can add SubItems again!

Of course I do not need:

 while(item.SubItems.Count > 0) { item.RemoveAt(0); } 

I AM?

+4
source share
3 answers

Unfortunately, ListView is a weird beast, and one of its weird angles is that its elements are just the set of values ​​that will be shown, one for each column.

The Name property simply automates placing something in the first column, and, unfortunately, this “something” lives in the SubItems collection.

This means that if you check the SubItems collection, you will notice that it already has one element, and after setting the element name you will see that the text of this element is equal to this name.

This is the code for the ListViewItem.Name property:

 public string Name { get { if (SubItemCount == 0) { return string.Empty; } else { return subItems[0].Name; } } set { SubItems[0].Name = value; } } 

And the ListViewSubItem.Name property looks like this:

 public string Name { get { return (name == null) ? "": name; } set { name = value; if (owner != null) { owner.UpdateSubItems(-1); } } } 

Thus, clearing the SubItems collection has the consequences of clearing the properties of this first item, as you discovered, in addition to removing any other item from the collection.

In fact, it happens that the collection is cleared, but any attempt to search the SubItems collection while it is empty will create a new collection with one item with default values. In the above example, code reading the SubItems collection will automatically assign a collection with one item to the internal field if the collection is not already there.

So yes, that’s how it works. "

In fact, to remove every subitem except the first, your loop should be:

 while (item.SubItems.Count > 1) item.SubItems.RemoveAt(1); 
+4
source

From MSDN :

Note

The first sub-item of ListViewItem.ListViewSubItemCollection is always the item to which the sub-items belong. When performing operations on sub-elements in a collection, it is imperative that instead of referencing the index position 1 of 0, to make changes to the first subposition.

Thus, clearing the collection of subtypes also clears the values ​​for the parent.

+3
source

Please note: 1:
ListViewItem.Text (not Name ) is ListViewItem.SubItems[0] , but:
ListViewItem.SubItems.Clear() also clears ListViewItem.Name !

So, if you are using SubItems.Clear , you need to restore both Name and Text (if you need them).

Pay attention to 2:
If you use *Key methods (e.g. ListView.Items.ContainsKey() or ListView.Items.RemoveByKey() ) to access items (instead of *Index ), take care of ListViewItem.Name , which is the key you need to pass these methods ...

What clever logic ...

In the case when someone is forced or wants to use ListView , I discovered another problem described in question 23007388 .

Since it can take a very long time to determine all this, I posted this answer, even this thread is a bit old.

0
source

All Articles