static private bool IsGroupValid(IntPtr hwnd, int groupID)
        {
            GroupManager manager = WindowsListView._groupsCollection [hwnd];

            // check group validity
            if (!manager.IsGroupIdValid(groupID))
            {
                // Group was disabled but we did not get the needed event
                // since for some things events are not being sent
                // (e.g: Going from some LV modes to - List mode, List mode does not have Groups)
                // alexsn @


                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            return(true);
        }
        static private bool IsGroupValid(IntPtr hwnd, int groupID)
        {
            GroupManager manager = WindowsListView._groupsCollection [hwnd];

            // check group validity
            if (!manager.IsGroupIdValid(groupID))
            {
                // Group was disabled but we did not get the needed event
                // since for some things events are not being sent
                // (e.g: Going from some LV modes to - List mode, List mode does not have Groups)
                // Microsoft - We may want to consider raising the event here
                // The M7 work on checking if LE is valid however is the better way of going
                // RemoveGroupAndRaiseLogicalChangedEvent(_hwnd);
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            return(true);
        }
        // utility method returning object describing current group
        static internal GroupManager.GroupInfo GetGroupInfo(IntPtr hwnd, int groupID)
        {
            GroupManager.GroupInfo groupInfo = GroupManager.GroupInfo.Null;

            // if groupmanager is not available GetManager(hwnd)
            // will raise needed event
            GroupManager manager = WindowsListView._groupsCollection [hwnd];

            groupInfo = manager.GetGroupInfo(groupID);
            if (!groupInfo)
            {
                // LV control did not raise the needed event
                // alexsn @


                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            return(groupInfo);
        }
        // utility method returning object describing current group
        static internal GroupManager.GroupInfo GetGroupInfo(IntPtr hwnd, int groupID)
        {
            GroupManager.GroupInfo groupInfo = GroupManager.GroupInfo.Null;

            // if groupmanager is not available GetManager(hwnd)
            // will raise needed event
            GroupManager manager = WindowsListView._groupsCollection [hwnd];

            groupInfo = manager.GetGroupInfo(groupID);
            if (!groupInfo)
            {
                // LV control did not raise the needed event
                // Microsoft - We may want to consider raising the event here
                // The M7 work on checking if LE is valid however is the better way of going
                //  RemoveGroupAndRaiseLogicalChangedEvent(_hwnd);
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            }

            return(groupInfo);
        }
        private static unsafe GroupManager InitializeManager(IntPtr hwnd)
        {
            bool isComctrlV6OnOsVerV6orHigher = Misc.IsComctrlV6OnOsVerV6orHigher(hwnd);

            int itemCount = WindowsListView.GetItemCount(hwnd);

            NativeMethods.LVITEM_V6 item = new NativeMethods.LVITEM_V6();
            item.mask = NativeMethods.LVIF_GROUPID;

            // The only place where the GroupManager gets constructed
            GroupManager manager = new GroupManager(itemCount, hwnd, isComctrlV6OnOsVerV6orHigher);

            if (isComctrlV6OnOsVerV6orHigher)
            {
                NativeMethods.LVITEMINDEX ii = new NativeMethods.LVITEMINDEX(-1, -1);

                int flags = NativeMethods.LVNI_VISIBLEONLY | NativeMethods.LVNI_VISIBLEORDER;

                // When a listview is being "grouped by" an item may be in more than one group.  The itemCount
                // is the number of unique items.  This loop may iterate for more than the unique items in the group.
                // We are taking advantage of that fact the the array list will expand if there are alot of duplicates.
                while (XSendMessage.XSend(hwnd, NativeMethods.LVM_GETNEXTITEMINDEX, new IntPtr(&ii), flags, Marshal.SizeOf(ii.GetType())))
                {
                    // need to convert the item id to a group id
                    NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6();
                    groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6)));
                    groupInfo.mask = NativeMethods.LVGF_GROUPID;

                    bool lresult = XSendMessage.XSend(hwnd, NativeMethods.LVM_GETGROUPINFOBYINDEX, new IntPtr(ii.iGroup), new IntPtr(&groupInfo), Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6)));
                    if (!lresult)
                    {
                        if (groupInfo.iGroupID == -1)
                        {
                            // A -1 here means that there are no duplicates in this grouped listview so
                            // we have to get the group the old way.  This is done for performance reasons.
                            break;
                        }
                        // no group for this item should never happen.
                        // If it ever does the other items might ok so just keep going.
                        continue;
                    }

                    if (!manager.Add(groupInfo.iGroupID, ii.iItem))
                    {
                        // we had problem adding item to the needed group at this point it makes no
                        // sense to continue
                        System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group");
                        return(null);
                    }
                }
            }

            bool sortNeeded = false;

            // If the code above did not yield anything try this way.  This will work for
            // listviews pre Vista and grouped listviews in vista that don't have duplicate items.
            if (manager.GroupCount() == 0)
            {
                // if we get the groups this way they need to be sorted.  The code above brings them in sorted.
                sortNeeded = true;
                int current = 0;
                while (current < itemCount)
                {
                    item.iItem = current;
                    if (XSendMessage.GetItem(hwnd, ref item) && manager.Add(item.iGroupID, item.iItem))
                    {
                        current++;
                    }
                    else
                    {
                        // we had problem adding item to the needed group at this point it makes no
                        // sense to continue
                        System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group");
                        return(null);
                    }
                }
            }

            // Sort items within the group
            int groupsCount = manager.GroupCount();

            for (int i = 0; i < groupsCount; i++)
            {
                Group group = (Group)manager._groups[i];
                Array.Sort(group.Items, 0, group.Count, new SortGroupItems(hwnd));
            }


            // Depending on how we got the group info we may need to sort it.
            // In vista the the listview can put the list items in the correct order.
            // Pre vista or old ui (v5) will always need to be sorted.
            if (sortNeeded)
            {
                // Sort groups
                manager._groups.Sort(new SortGroups(hwnd));
            }

            return(manager);
        }
        private static unsafe GroupManager InitializeManager(IntPtr hwnd)
        {
            bool isComctrlV6OnOsVerV6orHigher = Misc.IsComctrlV6OnOsVerV6orHigher(hwnd);
           
            int itemCount = WindowsListView.GetItemCount(hwnd);
            NativeMethods.LVITEM_V6 item = new NativeMethods.LVITEM_V6();
            item.mask = NativeMethods.LVIF_GROUPID;

            // The only place where the GroupManager gets constructed
            GroupManager manager = new GroupManager(itemCount, hwnd, isComctrlV6OnOsVerV6orHigher);
            
            if (isComctrlV6OnOsVerV6orHigher)
            {
                NativeMethods.LVITEMINDEX ii = new NativeMethods.LVITEMINDEX(-1, -1);

                int flags = NativeMethods.LVNI_VISIBLEONLY | NativeMethods.LVNI_VISIBLEORDER;

                // When a listview is being "grouped by" an item may be in more than one group.  The itemCount
                // is the number of unique items.  This loop may iterate for more than the unique items in the group.
                // We are taking advantage of that fact the the array list will expand if there are alot of duplicates.
                while (XSendMessage.XSend (hwnd, NativeMethods.LVM_GETNEXTITEMINDEX, new IntPtr(&ii), flags, Marshal.SizeOf(ii.GetType())))
                {
                    // need to convert the item id to a group id
                    NativeMethods.LVGROUP_V6 groupInfo = new NativeMethods.LVGROUP_V6();
                    groupInfo.Init(Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6)));
                    groupInfo.mask = NativeMethods.LVGF_GROUPID;
                    
                    bool lresult  = XSendMessage.XSend(hwnd, NativeMethods.LVM_GETGROUPINFOBYINDEX, new IntPtr(ii.iGroup), new IntPtr(&groupInfo), Marshal.SizeOf(typeof(NativeMethods.LVGROUP_V6)));
                    if (!lresult)
                    {
                        if (groupInfo.iGroupID == -1)
                        {
                            // A -1 here means that there are no duplicates in this grouped listview so
                            // we have to get the group the old way.  This is done for performance reasons.
                            break;
                        }
                        // no group for this item should never happen.  
                        // If it ever does the other items might ok so just keep going.
                        continue;
                    }
                    
                    if (!manager.Add(groupInfo.iGroupID, ii.iItem))
                    {
                        // we had problem adding item to the needed group at this point it makes no
                        // sense to continue
                        System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group");
                        return null;
                    }
                }
            }

            bool sortNeeded = false;
            // If the code above did not yield anything try this way.  This will work for 
            // listviews pre Vista and grouped listviews in vista that don't have duplicate items.
            if (manager.GroupCount() == 0)
            {
                // if we get the groups this way they need to be sorted.  The code above brings them in sorted.
                sortNeeded = true;
                int current = 0;
                while (current < itemCount)
                {
                    item.iItem = current;
                    if (XSendMessage.GetItem(hwnd, ref item) && manager.Add(item.iGroupID, item.iItem))
                    {
                        current++;
                    }
                    else
                    {
                        // we had problem adding item to the needed group at this point it makes no
                        // sense to continue
                        System.Diagnostics.Debug.Assert(false, "Cannot add item to the needed group");
                        return null;
                    }
                }
            }

            // Sort items within the group
            int groupsCount = manager.GroupCount();
            for (int i = 0; i < groupsCount; i++)
            {
                Group group = (Group)manager._groups[i];
                Array.Sort(group.Items, 0, group.Count, new SortGroupItems(hwnd));
            }


            // Depending on how we got the group info we may need to sort it.
            // In vista the the listview can put the list items in the correct order.
            // Pre vista or old ui (v5) will always need to be sorted.
            if (sortNeeded)
            {
                // Sort groups
                manager._groups.Sort(new SortGroups(hwnd));
            }
            
            return manager;
        }