folibis folibis - 4 days ago 5
C# Question

ListViewItem implicitly adds ListViewSubItem

Suppose I build

ListView
with following code:

ListViewItem item1 = new ListViewItem();
item1.Text = "item1";
item1.SubItems.Add(new ListViewItem.ListViewSubItem(item1, "subitem1"));
item1.SubItems.Add(new ListViewItem.ListViewSubItem(item1, "subitem2"));
listView1.Items.Add(item1);


But in fact it will create 3
ListViewSubItem
s like this:

ListViewItem
|
-------------------------------------
| | |
ListViewSubItem ListViewSubItem ListViewSubItem
(Text=item1) (Text=subitem1) (Text=subitem2)


In my real program I use custom subitems derived from
ListViewItem.ListViewSubItem
and
OwnerDraw = true


ListViewItem item1 = new ListViewItem();
CustomListViewSubItem subitem1 = new CustomListViewSubItem(item1, "subitem1");
CustomListViewSubItem subitem1 = new CustomListViewSubItem(item1, "subitem1");
listView1.Items.Add(item1);


and the above behavior breaks all the logic while casting in
DrawSubItems
event:

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
ListViewItem item = e.Item;
ListViewItem.ListViewSubItem subitem = item.SubItems[e.ColumnIndex];
CustomListViewSubItem customsubitem = (CustomListViewSubItem)subitem; // <- System.InvalidCastException here
...
}


Sure it will fail only for first subitem which in fact is item but that's not I want. How can I avoid this behavior and create only 2 subitems I need?

Answer

Not tested but may work:
By calling listView.SubItems on empty collection it automatically adds one "default" element. My advise would be to remove first element after adding your element like:

listView.SubItems.Add(new MeListViewSubItem( ... ) );
listView.SubItems.RemoveAt(0);

From ReferenceSource:

    /// <include file='doc\ListViewItem.uex' path='docs/doc[@for="ListViewItem.SubItems"]/*' />
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    [
    SRCategory(SR.CatData),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),        
    SRDescription(SR.ListViewItemSubItemsDescr),
    Editor("System.Windows.Forms.Design.ListViewSubItemCollectionEditor, " + AssemblyRef.SystemDesign,typeof(UITypeEditor)),
    ]
    public ListViewSubItemCollection SubItems {
        get {
            if (SubItemCount == 0) {
                subItems = new ListViewSubItem[1];
                subItems[0] = new ListViewSubItem(this, string.Empty);                        
                SubItemCount = 1;
            }

            if (listViewSubItemCollection == null) {
                listViewSubItemCollection = new ListViewSubItemCollection(this);
            }
            return listViewSubItemCollection;
        }
    }
Comments