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

点点圈 提交于 2020-01-30 05:21:53

问题


I am using a WinForms ListView in details mode (.NET 4.0, running on Windows 7) and I have a function that needs to clear the subitems in a particular item. Unfortunately when I do that it also clear's the name:

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

In the debugger I've tracked it down to this, and I've looked at the documentation on MSDN and it's unhelpful,

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

Except the ListViewItem is still very there because later in the function I'm able to add SubItems to it again!

Surely I don't have to:

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

Do I?


回答1:


Unfortunately ListView is a strange beast, and one of the strange corners of it is that its items are just a collection of values to be shown, one for each column.

The Name property just automates putting something into the first column, and unfortunately this "something" lives in the SubItems collection.

This means that if you inspect the SubItems collection, you'll notice that it has one element already, and after setting the name of the item, you'll see the text of that item is equal to that 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);
        }
    }
}

So, clearing the SubItems collection has the consequence of clearing the properties of that first item, as you've discovered, in addition to removing every other item from the collection.

Actually, what happens is that the collection is cleared, but any attempt to look at the SubItems collection while it is empty will create a new collection with one item, with default property values. In the above example code, reading the SubItems collection will automagically assign a collection with one item to the internal field, if the collection isn't already there.

So yes, this is how it "works".

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

while (item.SubItems.Count > 1)
    item.SubItems.RemoveAt(1);



回答2:


From MSDN:

Note

The first subitem in the ListViewItem.ListViewSubItemCollection is always the item that owns the subitems. When performing operations on subitems in the collection, be sure to reference index position 1 instead of 0 to make changes to the first subitem.

Thus, clearing the sub items collection, clears the values for the parent as well.




回答3:


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

So, if you use SubItems.Clear, you then have to restore both Name and Text (if you need them).

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

What a smart logic...

For the case anyone is forced or wants to use ListView I have discovered another problem described in question 23007388.

As it might take very long time to determine all this stuff, I have posted this answer even this thread is a little bit old.



来源:https://stackoverflow.com/questions/4097912/why-does-subitems-clear-also-delete-the-name-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!