开发者

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

开发者 https://www.devze.com 2023-01-23 18:10 出处:网络
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\'

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: Remov开发者_如何学JAVAes 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?


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);


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消