public DataGridCollectionViewGroupSort( int[] dataIndexArray, GroupSortComparer groupSortedComparer, DataGridCollectionViewGroup[] protectedItems )
      : base( dataIndexArray )
    {
      if( groupSortedComparer == null )
        throw new ArgumentNullException( "groupSortedComparer" );

      m_groupSortedComparer = groupSortedComparer;
      m_groups = protectedItems;
    }
    private DataGridCollectionViewGroup CreateSubGroup( object groupName, int level, ObservableCollection<GroupDescription> groupByList, GroupSortComparer[] groupSortComparers )
    {
      // If sortComparers is null, we are in massive group creation, no order check.
      DataGridCollectionViewGroup group = new DataGridCollectionViewGroup( groupName, this, m_nextSubGroupUnsortedIndex );

      unchecked
      {
        m_nextSubGroupUnsortedIndex++;
      }

      int index;

      if( groupSortComparers == null )
      {
        Debug.Assert( this.ProtectedItemCount == this.ProtectedItems.Count );
        index = this.ProtectedItemCount;
      }
      else
      {
        index = this.BinarySearchGroup( group, groupSortComparers[ level ] );

        if( index < 0 )
          index = ~index;
      }

      level++;

      if( level < groupByList.Count )
      {
        group.SetSubGroupBy( groupByList[ level ] );
        group.CreateFixedGroupNames( level, groupByList, groupSortComparers );
      }

      this.InsertGroup( index, group );
      return group;
    }
    internal void SortItems(
      SortDescriptionInfo[] sortDescriptionInfos,
      GroupSortComparer[] groupSortComparers,
      int level,
      List<RawItem> globalRawItems,
      DataGridCollectionViewGroup newSortedGroup )
    {
      int itemCount = this.ItemCount;

      if( itemCount == 0 )
        return;

      ObservableCollection<object> groupItems = this.ProtectedItems;

      if( this.IsBottomLevel )
      {
        int[] indexes;

        indexes = new int[ itemCount + 1 ];

        for( int i = 0; i < itemCount; i++ )
        {
          indexes[ i ] = m_sortedRawItems[ i ].Index;
        }

        // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
        DataGridCollectionViewSort collectionViewSort =
          new DataGridCollectionViewSort( indexes, sortDescriptionInfos );

        collectionViewSort.Sort( itemCount );
        int index = 0;

        for( int i = 1; i <= itemCount; i++ )
        {
          newSortedGroup.InsertRawItem( index, globalRawItems[ indexes[ i ] ] );
          index++;
        }
      }
      else
      {
        int[] indexes;

        indexes = new int[ itemCount + 1 ];

        for( int i = 0; i < itemCount; i++ )
        {
          indexes[ i ] = i;
        }

        // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
        DataGridCollectionViewGroupSort collectionViewSort =
          new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], this );

        collectionViewSort.Sort( itemCount );
        int index = 0;
        level++;

        for( int i = 1; i <= itemCount; i++ )
        {
          DataGridCollectionViewGroup oldGroup = ( DataGridCollectionViewGroup )groupItems[ indexes[ i ] ];
          DataGridCollectionViewGroup newGroup = new DataGridCollectionViewGroup( oldGroup, newSortedGroup );

          // Sort sub items
          oldGroup.SortItems( sortDescriptionInfos, groupSortComparers, level, globalRawItems, newGroup );

          newSortedGroup.InsertGroup( index, newGroup );
          index++;
        }
      }
    }
    internal void CreateFixedGroupNames( int fixedGroupLevel, ObservableCollection<GroupDescription> groupByList, GroupSortComparer[] groupSortComparers )
    {
      GroupDescription groupDescription = this.SubGroupBy;

      if( groupDescription == null )
        return;

      Debug.Assert( groupByList[ fixedGroupLevel ] == this.SubGroupBy );

      ObservableCollection<object> groupNames = groupDescription.GroupNames;
      int count = groupNames.Count;

      for( int i = 0; i < count; i++ )
      {
        this.CreateSubGroup( groupNames[ i ], fixedGroupLevel, groupByList, groupSortComparers );
      }
    }
    internal DataGridCollectionViewGroup GetGroup(
      RawItem rawItem,
      int level,
      CultureInfo culture,
      ObservableCollection<GroupDescription> groupByList,
      GroupSortComparer[] groupSortComparers )
    {
      // If sortComparers is null, we are in massive group creation, no order check.

      if( this.IsBottomLevel )
        throw new InvalidOperationException( "An attempt was made to get a group for which a GroupDescription has not been provided." );

      object groupName = m_subGroupBy.GroupNameFromItem( rawItem.DataItem, level, culture );
      DataGridGroupDescription dataGridGroupDescription = m_subGroupBy as DataGridGroupDescription;
      DataGridCollectionViewGroup group;

      if( dataGridGroupDescription != null )
      {
        group = m_groupsDictionary[ DataGridCollectionViewGroup.GetHashKeyFromName( groupName ) ]
          as DataGridCollectionViewGroup;
      }
      else
      {
        int itemCount = this.ItemCount;
        group = null;

        for( int i = 0; i < itemCount; i++ )
        {
          DataGridCollectionViewGroup tempGroup = this.ProtectedItems[ i ] as DataGridCollectionViewGroup;

          if( m_subGroupBy.NamesMatch( tempGroup.Name, groupName ) )
          {
            group = tempGroup;
            break;
          }
        }
      }

      if( group == null )
      {
        group = this.CreateSubGroup(
          groupName, level, groupByList, groupSortComparers );
      }

      return group;
    }