简体   繁体   中英

Empty ListViewGroup is not shown in ListView

I could not find any remarks on MSDN ListView.Groups Property that empty ListViewGroup will be hidden. Is it by design, or I am missing something? My sample code below will show only "group 2" with item "item1".

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles MyBase.Load
    '
    Dim gr = New ListViewGroup("group 1")
    ListView1.Groups.Add(gr)
    '
    Dim gr2 = New ListViewGroup("group 2")
    ListView1.Groups.Add(gr2)
    '
    Dim lvi As New ListViewItem("item1")
    ListView1.Items.Add(lvi)
    '
    gr2.Items.Add(lvi)
End Sub

Updated: Is there are any way to show ListViewGroup without adding dummy item

For now the only workaround idea I have is to use collapsible listview (Vista and up)

Better ListView can do exactly this. There is a ShowEmptyGroups property that does the trick:

Better ListView中的空组

There is also a Better ListView Express , which is freeware and supports groups as well. It is not a ListView wrapper, but a complete re-implementation of all features, 100% managed and just made... better :-)

Is not possible by Microsoft design.
Look at this discussion on social.msdn.microsoft.com .
Don't be fooled by title. It talks about empty groups.

this method makes sure the ListViewGroup shows

void MakeSureListViewGroupHeaderShows(ListView lv)
{
    foreach (ListViewGroup lvg in lv.Groups)
    {
        if (lvg.Items.Count == 0)
        {
            // add empty list view item
            ListViewItem lvi = new ListViewItem(string.Empty);
            lvi.Group = lvg;
            lv.Items.Add(lvi);
        }
        else
        {
            // remove our dummy list view item
            foreach (ListViewItem lvi in lvg.Items)
            {
                if (lvi.Text == string.Empty)
                {
                    lvi.Remove();
                }
            }
        }
    }
}

The hack I'm talking about up above IS NOT RECOMMENDED. However, if you REALLY want empty groups to show up, then you would just delegate the adding code to a separate utility method that checks if the group is empty. If it is, then it adds it to the "default" group (so it at least shows up) until you add an item to it.

public static void AddGroup(this ListView lv, ListViewGroup lg)
{
    if (lg.Items.Count > 0 || lv.Items.Cast<ListViewItem>().Any(tg => tg.Group == lg))
        lv.Groups.Add(lg);
    else
    {
        var item = lv.Items.Add(lg.Header);
        item.Tag = lg;
    }
}

public static void AddItem(this ListView lv, ListViewItem li, string groupKey) // Could also take ListViewGroup here...
{
    if (lv.Groups[groupKey] == null && lv.Items.ContainsKey(groupKey))
    {
        lv.Groups.Add((ListViewGroup)lv.Items[groupKey].Tag);
        lv.Items.RemoveByKey(groupKey);
    }
    lv.Items.Add(li);
    li.Group = lv.Groups[groupKey];
}

public static void AddItem(this ListView lv, ListViewItem li, ListViewGroup lg)
{
    lv.AddItem(li, lg.Header);
}

Another warning, NOT RECOMMENDED. This is quite a bit of overhead, and not really worth the trouble (IMO). But hey, to each their own. This code is completely untested, and just throwing it out there in case you really NEED this to work (which should never be the case, better to look for alternatives). The worst part is that the Group declaration pretty much just resides within the ListItem itself, that way you can just change the group rather easily.

Last warning, NOT RECOMMENDED.

Edit: I've modified the code above to be extension methods on ListView objects, that way you have direct access to the ListView from the methods. Anytime you add a group, you would just call listView.AddGroup , adding an item you can use of the listView.AddItem methods. This is opposed to listView.Items.Add and listView.Groups.Add methods. The one thing to keep in mind is that you don't need to assign Items to the Groups, but instead only assign the Groups to the Items. This makes it so you can switch items between groups by changing the reference, instead of having to remove/add references between groups. This also assumes that you've declared the Header of the ListItemGroup to be the same as the Key (in other words, new ListItemGroup("HeaderText" /*KEY*/, "HeaderText" /*HEADER*/) . Otherwise, you'd just have to change the logic within AddItem to reference the proper value (which is Name , usually).

"I ran into the same issue earlier this year in considering the display of empty groups. Microsoft, by-design, does not display a group name that is empty of any items. What you have to do is create/add an empty item or item holding a blank character of text to the group. When you have actual data item(s) to populate for that group, you must then remember to delete the empty/blank item from that group."

Source: http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/39681a70-d992-4046-ad7e-21a2e33791b1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM