protected CollectionGeneratorNode( IList list, GeneratorNode parent )
      : base( parent )
    {
      Debug.Assert( list != null, "list cannot be null for CollectionGeneratorNode" );

      m_items = list;
    }
    public GroupGeneratorNode( CollectionViewGroup group, GeneratorNode parent, GroupConfiguration groupConfig )
      : base( parent )
    {
      Debug.Assert( group != null, "group cannot be null for GroupGeneratorNode" );
      Debug.Assert( groupConfig != null );

      m_group = group;
      m_groupConfig = groupConfig;
    }
    public GeneratorNodeHelper( GeneratorNode initialPointer, int index, int sourceDataIndex )
    {
      if( initialPointer == null )
        throw new ArgumentNullException( "initialPointer" );

      m_currentNode = initialPointer;
      m_index = index;
      m_sourceDataIndex = sourceDataIndex;
    }
    private readonly WeakReference m_dataGridControl; //null

    #endregion

    public GeneratorNode CreateGroupGeneratorNode(
      CollectionViewGroup collectionViewGroup,
      GeneratorNode parent,
      GeneratorNode previous,
      GeneratorNode next,
      GroupConfiguration groupConfig )
    {
      Debug.Assert( collectionViewGroup != null, "collectionViewGroup cannot be null for CreateGroupGeneratorNode()" );

      GroupGeneratorNode node = new GroupGeneratorNode( collectionViewGroup, parent, groupConfig );

      if( previous != null )
      {
        previous.Next = node;
      }
      node.Previous = previous;

      if( next != null )
      {
        next.Previous = node;
      }
      node.Next = next;

      node.IsExpanded = groupConfig.InitiallyExpanded;

      if( !collectionViewGroup.IsBottomLevel )
      {
        this.RegisterNodeCollectionChanged(
          ( INotifyCollectionChanged )collectionViewGroup.GetItems(),
          new NotifyCollectionChangedEventHandler( node.OnCollectionChanged ) );

        node.CollectionChanged += m_groupsChangedHandler;
      }

      node.ExpansionStateChanged += m_expansionStateChangedHandler;
      node.IsExpandedChanging += m_isExpandedChangingHandler;
      node.IsExpandedChanged += m_isExpandedChangedHandler;

      node.AdjustItemCount( node.ItemCount );

      node.BuildNamesTree();

      return node;
    }
示例#5
0
        public void CleanGeneratorNode(GeneratorNode node)
        {
            HeadersFootersGeneratorNode headersFootersNode = node as HeadersFootersGeneratorNode;

            if (headersFootersNode != null)
            {
                this.CleanHeadersFootersNotification(headersFootersNode);
            }
            else
            {
                ItemsGeneratorNode itemsNode = node as ItemsGeneratorNode;
                if (itemsNode != null)
                {
                    this.UnregisterNodeCollectionChanged(( INotifyCollectionChanged )itemsNode.Items);
                    itemsNode.CollectionChanged -= m_itemsChangedHandler;
                }
                else
                {
                    GroupGeneratorNode groupNode = node as GroupGeneratorNode;
                    if (groupNode != null)
                    {
                        IList <object> subItems = groupNode.CollectionViewGroup.GetItems();

                        this.UnregisterNodeCollectionChanged(( INotifyCollectionChanged )subItems);

                        groupNode.CollectionChanged  -= m_groupsChangedHandler;
                        groupNode.IsExpandedChanging -= m_isExpandedChangingHandler;
                        groupNode.IsExpandedChanged  -= m_isExpandedChangedHandler;
                    }
                }
            }

            node.ExpansionStateChanged -= m_expansionStateChangedHandler;

            node.CleanGeneratorNode();
        }
    private DependencyObject CreateContainerForItem( object dataItem, GeneratorNode node )
    {
      DependencyObject retval = null;

      if( node is HeadersFootersGeneratorNode )
      {
        retval = this.CreateHeaderFooterContainer( dataItem );
        if( node.Parent == null )
        {
          GroupLevelIndicatorPane.SetGroupLevel( retval, -1 );
        }
        else
        {
          GroupLevelIndicatorPane.SetGroupLevel( retval, node.Level );
        }

        this.SetStatContext( retval, node );
      }
      else if( node is ItemsGeneratorNode )
      {
        //ensure that item is not its own container...
        if( !this.IsItemItsOwnContainer( dataItem ) )
        {
          retval = this.CreateNextItemContainer();
        }
        else
        {
          retval = dataItem as DependencyObject;
        }

        GroupLevelIndicatorPane.SetGroupLevel( retval, node.Level );
      }
      else
      {
        throw new DataGridInternalException();
      }

      if( retval == null )
      {
        throw new DataGridInternalException();
      }

      CustomItemContainerGenerator.SetDataItemProperty( retval, dataItem );
      DataGridControl.SetDataGridContext( retval, m_dataGridContext );

      return retval;
    }
    private void HandleItemReset( GeneratorNode node )
    {
      //these 4 variables will hold the content for the Removal and the re-addition of the items.
      int countGeneratedRemoved;
      GeneratorPosition itemGenPos;

      List<DependencyObject> removedContainers = new List<DependencyObject>();

      //by definition, items from a node are contiguous...
      itemGenPos = this.FindFirstRealizedItemsForNode( node );
      int removeIndex = ( itemGenPos.Offset == 0 ) ? m_genPosToIndex[ itemGenPos.Index ] : -1;
      countGeneratedRemoved = this.RemoveGeneratedItems( node, removedContainers );

      // ensure that the mapping of the details to that node are removed!
      ItemsGeneratorNode itemsNode = node as ItemsGeneratorNode;
      if( ( itemsNode != null ) && ( itemsNode.Details != null ) )
      {
        int detailCount = 0;
        foreach( List<DetailGeneratorNode> detailList in itemsNode.Details.Values )
        {
          foreach( DetailGeneratorNode detailNode in detailList )
          {
            detailCount += detailNode.ItemCount;
          }
        }

#if LOG
        Log.WriteLine( this, "details.Clear - IN" + itemsNode.GetHashCode().ToString() );
#endif

        itemsNode.Details.Clear();
        itemsNode.Details = null;

        node.AdjustItemCount( -detailCount );
      }

      //send the removal notification to the panel...
      this.IncrementCurrentGenerationCount();

      if( countGeneratedRemoved > 0 )
      {
        this.SendRemoveEvent( itemGenPos, removeIndex, 0, countGeneratedRemoved, removedContainers );
      }
    }
    private GeneratorNode HandleParentGroupAddition( GeneratorNode parent, out int countAdded, NotifyCollectionChangedEventArgs e )
    {
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( parent, 0, 0 ); //do not care about index (for now).

      //start by moving to the first child... of the node (GroupHeaders node, most probably).
      if( !nodeHelper.MoveToChild( false ) ) //case 120137: false parameter is to prevent skipping over a collapsed node (item count 0 )
      {
        //could not advance to the child item so there is no items to be removed...

        throw new DataGridInternalException();
      }

      return this.HandleSameLevelGroupAddition( nodeHelper.CurrentNode, out countAdded, e );
    }
    private void HandleSameLevelGroupMove( GeneratorNode node, NotifyCollectionChangedEventArgs e )
    {
      GroupGeneratorNode parentGroup = node.Parent as GroupGeneratorNode;

      //Start a NodeHelper on the first child of the node where the move occured.
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( node, 0, 0 );
      nodeHelper.ReverseCalculateIndex(); //determine index of the node.

      //Advance to the first "Group" node (skip the GroupHEaders)
      while( !( nodeHelper.CurrentNode is GroupGeneratorNode ) )
      {
        if( !nodeHelper.MoveToNext() )
          throw new DataGridInternalException();
      }

      //then move up to the removal start point.
      if( !nodeHelper.MoveToNextBy( e.OldStartingIndex ) )
      {
        throw new DataGridInternalException();
      }

      //remember the current node as the start point of the move (will be used when "extracting the chain")
      GeneratorNode startNode = nodeHelper.CurrentNode;
      //also remember the index of the node, to calculate range of elements to remove (containers )
      int startIndex = nodeHelper.Index;

      //then, cumulate the total number of items in the groups concerned
      int totalCountRemoved = 0;

      node = this.ProcessGroupRemoval( startNode, e.OldItems.Count, false, out totalCountRemoved );

      //send a message to the panel to remove the visual elements concerned 
      GeneratorPosition removeGenPos = this.GeneratorPositionFromIndex( startIndex );

      List<DependencyObject> removedContainers = new List<DependencyObject>();
      int genCountRemoved = this.RemoveGeneratedItems( startIndex, startIndex + totalCountRemoved - 1, removedContainers );

      this.SendRemoveEvent( removeGenPos, startIndex, totalCountRemoved, genCountRemoved, removedContainers );

      //reset the node parameter for the "re-addition"
      node = ( parentGroup != null ) ? parentGroup.Child : m_firstItem;

      if( node == null )
        throw new DataGridInternalException();

      //Once the chain was pulled out, re-insert it at the appropriate location.
      nodeHelper = new GeneratorNodeHelper( node, 0, 0 ); //do not care about the index for what I need

      //Advance to the first "Group" node (skip the GroupHEaders)
      while( !( nodeHelper.CurrentNode is GroupGeneratorNode ) )
      {
        if( !nodeHelper.MoveToNext() )
          throw new DataGridInternalException();
      }

      bool insertBefore = nodeHelper.MoveToNextBy( e.NewStartingIndex );

      if( insertBefore )
      {
        if( nodeHelper.CurrentNode == m_firstItem )
        {
          if( m_startNode == m_firstItem )
          {
            m_startNode = startNode;
          }

          m_firstItem = startNode;
        }

        //reinsert the chain at the specified location.
        nodeHelper.InsertBefore( startNode );
      }
      else
      {
        nodeHelper.InsertAfter( startNode );
      }

      //and finally, call to increment the generation count for the generator content
      this.IncrementCurrentGenerationCount();
    }
    public static GeneratorNode EvaluateChain( GeneratorNode chainStart, out int totalChildCount, out int chainLength )
    {
      //if we insert a chain of nodes, this GeneratorNodeHelper will help us
      GeneratorNodeHelper newHelper = new GeneratorNodeHelper( chainStart, 0, 0 );

      //first determine the total number of childs from this "node"
      totalChildCount = 0;
      chainLength = 0;

      do
      {
        totalChildCount += newHelper.CurrentNode.ItemCount;
        chainLength++;
      }
      while( newHelper.MoveToNext() );

      //then, since we moved at the end of the "chain"
      return newHelper.CurrentNode;
    }
    public bool InsertAfter( GeneratorNode insert )
    {
      if( insert == null )
        throw new DataGridInternalException( "GeneratorNode is null." );

      int insertionCount;
      int chainLength;
      GeneratorNode insertLast = GeneratorNodeHelper.EvaluateChain( insert, out insertionCount, out chainLength );

      if( m_currentNode.Next != null )
      {
        m_currentNode.Next.Previous = insertLast;
      }

      insertLast.Next = m_currentNode.Next;
      insert.Previous = m_currentNode;
      m_currentNode.Next = insert;

      // Move the current node to the last node inserted
      if( !this.MoveToNextBy( chainLength ) )
        throw new DataGridInternalException( "Unable to move to the requested generator index." );

      return true;
    }
示例#12
0
 public ItemsGeneratorNode(IList list, GeneratorNode parent)
     : base(list, parent)
 {
 }
    private void SetupCollectionGeneratorNode( CollectionGeneratorNode newNode, GeneratorNode parent, GeneratorNode previous, GeneratorNode next )
    {
      if( previous != null )
      {
        previous.Next = newNode;
      }
      newNode.Previous = previous;

      if( next != null )
      {
        next.Previous = newNode;
      }
      newNode.Next = next;

      this.RegisterNodeCollectionChanged( ( INotifyCollectionChanged )newNode.Items, new NotifyCollectionChangedEventHandler( newNode.OnCollectionChanged ) );

      newNode.CollectionChanged += m_itemsChangedHandler;
      newNode.ExpansionStateChanged += m_expansionStateChangedHandler;

      if( parent != null )
      {
        newNode.AdjustItemCount( newNode.ItemCount );
      }
    }
    public void CleanGeneratorNode( GeneratorNode node )
    {
      HeadersFootersGeneratorNode headersFootersNode = node as HeadersFootersGeneratorNode;
      if( headersFootersNode != null )
      {
        this.CleanHeadersFootersNotification( headersFootersNode );
      }
      else
      {
        ItemsGeneratorNode itemsNode = node as ItemsGeneratorNode;
        if( itemsNode != null )
        {
          this.UnregisterNodeCollectionChanged( ( INotifyCollectionChanged )itemsNode.Items );
          itemsNode.CollectionChanged -= m_itemsChangedHandler;
        }
        else
        {
          GroupGeneratorNode groupNode = node as GroupGeneratorNode;
          if( groupNode != null )
          {
            IList<object> subItems = groupNode.CollectionViewGroup.GetItems();

            this.UnregisterNodeCollectionChanged( ( INotifyCollectionChanged )subItems );

            groupNode.CollectionChanged -= m_groupsChangedHandler;
            groupNode.IsExpandedChanging -= m_isExpandedChangingHandler;
            groupNode.IsExpandedChanged -= m_isExpandedChangedHandler;
          }
        }
      }

      node.ExpansionStateChanged -= m_expansionStateChangedHandler;

      node.CleanGeneratorNode();
    }
    public void CleanGeneratorNodeTree( GeneratorNode node )
    {
      if( node.Parent != null )
      {
        node.Parent.AdjustItemCount( -node.ItemCount );

        GroupGeneratorNode parentGroupNode = node.Parent as GroupGeneratorNode;
        if( ( parentGroupNode != null ) && ( parentGroupNode.Child == node ) )
        {
          parentGroupNode.Child = null;
        }
      }

      GeneratorNode child;
      GeneratorNode next;

      do
      {
        GroupGeneratorNode groupNode = node as GroupGeneratorNode;

        next = node.Next;
        child = ( groupNode != null ) ? groupNode.Child : null;

        this.CleanGeneratorNode( node );

        //this recursive function cleans up the tree of nodes
        if( child != null )
        {
          this.CleanGeneratorNodeTree( child );
        }

        node = next;
      }
      while( node != null );
    }
    public HeadersFootersGeneratorNode CreateHeadersFootersGeneratorNode(
      IList collection,
      GeneratorNode parent,
      GeneratorNode previous,
      GeneratorNode next )
    {
      Debug.Assert( collection != null, "collection cannot be null for CreateHeadersFootersGeneratorNode()" );

      INotifyCollectionChanged notifyCollection = collection as INotifyCollectionChanged;

      Debug.Assert( notifyCollection != null, "collection must be a INotifyCollectionChanged for CreateHeadersFootersGeneratorNode()" );

      HeadersFootersGeneratorNode node = new HeadersFootersGeneratorNode( collection, parent );

      if( previous != null )
      {
        previous.Next = node;
      }
      node.Previous = previous;

      if( next != null )
      {
        next.Previous = node;
      }
      node.Next = next;

      node.ExpansionStateChanged += m_expansionStateChangedHandler;

      this.ConfigureHeadersFootersNotification( notifyCollection, node );

      if( parent != null )
      {
        node.AdjustItemCount( node.ItemCount );
      }

      return node;
    }
    public GeneratorNode CreateItemsGeneratorNode(
      IList collection,
      GeneratorNode parent,
      GeneratorNode previous,
      GeneratorNode next,
      CustomItemContainerGenerator generator )
    {
      Debug.Assert( collection != null, "collection cannot be null for CreateItemsGeneratorNode()" );
      Debug.Assert( generator != null );

      INotifyCollectionChanged notifyCollection = collection as INotifyCollectionChanged;

      Debug.Assert( notifyCollection != null, "collection must be a INotifyCollectionChanged for CreateItemsGeneratorNode()" );

      ItemCollection itemCollection = collection as ItemCollection;
      if( itemCollection != null )
      {
        DataGridCollectionView dgcv = itemCollection.SourceCollection as DataGridCollectionView;
        if( dgcv != null )
        {
          collection = dgcv;
        }
      }

      ItemsGeneratorNode node = new ItemsGeneratorNode( collection, parent );

      this.SetupCollectionGeneratorNode( node, parent, previous, next );


      node.AdjustLeafCount( node.Items.Count );

      return node;
    }
示例#18
0
    public ItemsGeneratorNode( IList list, GeneratorNode parent )
      : base( list, parent )
    {

    }
    private int RemoveGeneratedItems( GeneratorNode referenceNode, IList<DependencyObject> removedContainers )
    {
      int genCountRemoved = 0;

      List<GeneratorNode> toRemove = new List<GeneratorNode>();
      toRemove.Add( referenceNode );

      ItemsGeneratorNode itemsNode = referenceNode as ItemsGeneratorNode;
      if( itemsNode != null )
      {
        if( itemsNode.Details != null )
        {
          //cycle through all the details currently mapped to the reference node
          foreach( KeyValuePair<int, List<DetailGeneratorNode>> detailsForNode in itemsNode.Details )
          {
            foreach( DetailGeneratorNode detailNode in detailsForNode.Value )
            {
              toRemove.Add( detailNode );
            }
          }
        }
      }

      //cycle through the list of generated items, and see if any items are from the reference node passed.
      //start from the end so that removing an item will not cause the indexes to shift
      for( int i = m_genPosToNode.Count - 1; i >= 0; i-- )
      {
        GeneratorNode node = m_genPosToNode[ i ];

        //if the item is within the range removed
        if( toRemove.Contains( node ) )
        {
          //this will ensure to recurse the call to the appropriate Detail Generator for clearing of the container.
          //otherwise, it will only remove it from the list of container generated in the current generator instance.
          this.RemoveGeneratedItem( i, removedContainers );

          //increment realized item count removed
          genCountRemoved++;
        }
      }

      return genCountRemoved;
    }
示例#20
0
        //FindItem skips over itemless nodes.
        public int FindItem(object item)
        {
            //finding items can only be done in "forward" direction
            int retval = -1;

            GeneratorNode originalNode            = m_currentNode;
            int           originalIndex           = m_index;
            int           originalSourceDataIndex = m_sourceDataIndex;

            while (retval == -1)
            {
                ItemsGeneratorNode itemsNode = m_currentNode as ItemsGeneratorNode;

                if (itemsNode != null)
                {
                    int tmpIndex = itemsNode.Items.IndexOf(item);
                    if (tmpIndex > -1)
                    {
                        tmpIndex += itemsNode.CountDetailsBeforeDataIndex(tmpIndex);
                        //item is directly from this items node... then return the appropriate index!
                        retval = m_index + tmpIndex;
                        break;
                    }
                    else
                    {
                        //if the item is from a detail, then I don't want to "use" it!!!
                        retval = -1;
                        //but continue looping.... to find occurances of this item somewhere else in the tree
                    }
                }
                else
                {
                    CollectionGeneratorNode collectionNode = m_currentNode as CollectionGeneratorNode;

                    if (collectionNode != null)
                    {
                        int tmpIndex = collectionNode.IndexOf(item);

                        if (tmpIndex != -1)
                        {
                            retval = m_index + tmpIndex;
                            break;
                        }
                    }
                }

                //if we reach this point, it's because the item we are looking
                //for is not in this node... Try to access the child
                if (this.MoveToChild())
                {
                    continue;
                }

                //if we reach this point, it's because we have no child...
                if (this.MoveToNext())
                {
                    continue;
                }

                //final try, try "advancing" to the next item.
                if (this.MoveToFollowing())
                {
                    continue;
                }

                //up to this, we are in an endpoint, we failed.
                break;
            }

            if (retval == -1)
            {
                m_currentNode     = originalNode;
                m_index           = originalIndex;
                m_sourceDataIndex = originalSourceDataIndex;
            }

            return(retval);
        }
    private GeneratorNode SetupGroupHeaders( GroupConfiguration groupConfig, GeneratorNode actualNode )
    {
      if( groupConfig == null )
      {
        return new GeneratorNode( actualNode );
      }

      return this.NodeFactory.CreateHeadersFootersGeneratorNode( groupConfig.Headers, actualNode, null, null );
    }
        private void SetupCollectionGeneratorNode(CollectionGeneratorNode newNode, GeneratorNode parent, GeneratorNode previous, GeneratorNode next)
        {
            if (previous != null)
            {
                previous.Next = newNode;
            }
            newNode.Previous = previous;

            if (next != null)
            {
                next.Previous = newNode;
            }
            newNode.Next = next;

            this.RegisterNodeCollectionChanged(( INotifyCollectionChanged )newNode.Items, new NotifyCollectionChangedEventHandler(newNode.OnCollectionChanged));

            newNode.CollectionChanged     += m_itemsChangedHandler;
            newNode.ExpansionStateChanged += m_expansionStateChangedHandler;

            if (parent != null)
            {
                newNode.AdjustItemCount(newNode.ItemCount);
            }
        }
    private GeneratorPosition HandleSameLevelGroupRemove( GeneratorNode firstChild, out int countRemoved, out int genCountRemoved, out int removeIndex, NotifyCollectionChangedEventArgs e, IList<DependencyObject> removedContainers )
    {
      GeneratorPosition retval;

      countRemoved = 0;
      genCountRemoved = 0;

      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( firstChild, 0, 0 );
      nodeHelper.ReverseCalculateIndex();

      //Advance to the first "Group" node (skip the GroupHEaders)
      while( !( nodeHelper.CurrentNode is GroupGeneratorNode ) )
      {
        if( !nodeHelper.MoveToNext() )
          throw new DataGridInternalException();
      }

      //then move up to the removal start point.
      if( !nodeHelper.MoveToNextBy( e.OldStartingIndex ) )
      {
        throw new DataGridInternalException();
      }

      GroupGeneratorNode startNode = nodeHelper.CurrentNode as GroupGeneratorNode;
      removeIndex = -1;

      //Only fetch the index if the group itself is not "collapsed" or under a collapsed group already
      if( ( startNode.IsExpanded == startNode.IsComputedExpanded ) && ( startNode.ItemCount > 0 ) )
      {
        removeIndex = nodeHelper.Index;
        retval = this.GeneratorPositionFromIndex( removeIndex );
      }
      else
      {
        retval = new GeneratorPosition( -1, 1 );
      }

      //retrieve the generator position for the first item to remove.

      this.ProcessGroupRemoval( startNode, e.OldItems.Count, true, out countRemoved );

      //Clean the chain "isolated" previously
      this.NodeFactory.CleanGeneratorNodeTree( startNode );

      if( removeIndex != -1 )
      {
        //remove the appropriate 
        genCountRemoved = this.RemoveGeneratedItems( removeIndex, removeIndex + countRemoved - 1, removedContainers );
      }

      return retval;
    }
    private bool FindGeneratorListMappingInformationForContainer(
      DependencyObject container,
      out GeneratorNode containerNode,
      out int containerRealizedIndex,
      out object containerDataItem )
    {
      int index = m_genPosToContainer.IndexOf( container );

      if( index == -1 )
      {
        containerNode = null;
        containerRealizedIndex = -1;
        containerDataItem = null;

        return false;
      }

      containerNode = m_genPosToNode[ index ];
      containerRealizedIndex = m_genPosToIndex[ index ];
      containerDataItem = m_genPosToItem[ index ];

      return true;
    }
    public bool InsertBefore( GeneratorNode insert )
    {
      if( insert == null )
        throw new DataGridInternalException( "GeneratorNode is null" );

      int insertionCount;
      int chainLength;
      GeneratorNode insertLast = GeneratorNodeHelper.EvaluateChain( insert, out insertionCount, out chainLength );
      GeneratorNode previous = m_currentNode.Previous;

      if( previous != null )
      {
        previous.Next = insert;
      }

      insert.Previous = previous;
      m_currentNode.Previous = insertLast;
      insertLast.Next = m_currentNode;

      GroupGeneratorNode parentGroup = insert.Parent as GroupGeneratorNode;

      if( parentGroup != null )
      {
        if( parentGroup.Child == m_currentNode )
        {
          parentGroup.Child = insert;
        }
      }

      // Move the current to the first item inserted.
      // No need to change m_index, m_sourceDataIndex since they will still be with the correct value.
      m_currentNode = insert;
      return true;
    }
    private GeneratorNode CreateGroupListFromCollection( IList collection, GeneratorNode parentNode )
    {
      GeneratorNode rootNode = null;
      GeneratorNode previousNode = null;
      GroupGeneratorNode actualNode = null;

      GeneratorNode childNode = null;
      int level = ( parentNode == null ) ? 0 : parentNode.Level + 1;
      GroupConfiguration groupConfig;
      bool initiallyExpanded;

      ObservableCollection<GroupDescription> groupDescriptions = DataGridContext.GetGroupDescriptionsHelper( m_collectionView );
      GroupConfigurationSelector groupConfigurationSelector = m_dataGridContext.GroupConfigurationSelector;


      foreach( CollectionViewGroup group in collection )
      {
        groupConfig = GroupConfiguration.GetGroupConfiguration( m_dataGridContext, groupDescriptions, groupConfigurationSelector, level, group );

        Debug.Assert( groupConfig != null, "groupConfig != null" );
#if LOG
        Log.Assert( this, groupConfig != null, "groupConfig != null" );
#endif

        if( groupConfig.UseDefaultHeadersFooters )
          groupConfig.AddDefaultHeadersFooters();

        initiallyExpanded = groupConfig.InitiallyExpanded;

        actualNode = ( GroupGeneratorNode )this.NodeFactory.CreateGroupGeneratorNode( group, parentNode, previousNode, null, groupConfig );
        m_groupNodeMappingCache.Add( group, actualNode );

        if( rootNode == null )
        {
          rootNode = actualNode;
        }

        previousNode = actualNode;

        actualNode.UIGroup = new Group( actualNode, group, m_dataGridContext.GroupLevelDescriptions, m_dataGridContext );

        //Independently if the Group is the bottom level or not, we need to setup GroupHeaders
        childNode = this.SetupGroupHeaders( groupConfig, actualNode );
        actualNode.Child = childNode;

        GeneratorNodeHelper childNodeHelper = new GeneratorNodeHelper( childNode, 0, 0 ); //do not care about index.
        childNodeHelper.MoveToEnd(); //extensibility, just in case SetupGroupHeaders() ever return a node list.


        IList<object> subItems = group.GetItems();

        //if the node newly created is not the bottom level
        if( !group.IsBottomLevel )
        {
          if( ( subItems != null ) && ( subItems.Count > 0 ) )
          {
            GeneratorNode subGroupsNode = this.CreateGroupListFromCollection( subItems as IList, actualNode );
            if( subGroupsNode != null )
            {
              childNodeHelper.InsertAfter( subGroupsNode );
            }
          }
        }
        else
        {
          //this is the bottom level, create an Items node
          GeneratorNode itemsNode = this.NodeFactory.CreateItemsGeneratorNode( subItems as IList, actualNode, null, null, this );
          if( itemsNode != null )
          {
            childNodeHelper.InsertAfter( itemsNode );
          }
        }

        childNodeHelper.InsertAfter( this.SetupGroupFooters( groupConfig, actualNode ) );
      }

      return rootNode;
    }
示例#27
0
    //-------------
    // Methods

    internal virtual void CleanGeneratorNode()
    {
      this.Previous = null;
      this.Parent = null;
      this.Next = null;
    }
    private GeneratorPosition HandleParentGroupRemove( GeneratorNode parent, out int countRemoved, out int genCountRemoved, out int removeIndex, NotifyCollectionChangedEventArgs e, IList<DependencyObject> removedContainers )
    {
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( parent, 0, 0 ); //do not care about index (for now).

      // start by moving to the first child... of the node (GroupHeaders node, most probably).
      // false parameter is to prevent skipping over a collapsed node (item count 0 )
      if( !nodeHelper.MoveToChild( false ) )
      {
        //could not advance to the child item so there is no items to be removed...
        throw new DataGridInternalException();
      }

      return this.HandleSameLevelGroupRemove( nodeHelper.CurrentNode, out countRemoved, out genCountRemoved, out removeIndex, e, removedContainers );
    }
示例#29
0
 internal GeneratorNode( GeneratorNode parent )
 {
   this.Parent = parent;
 }
    private GroupGeneratorNode ProcessGroupRemoval(
      GeneratorNode startNode,
      int removeCount,
      bool updateGroupNodeMappingCache,
      out int countRemoved )
    {

      Debug.Assert( removeCount != 0, "remove count cannot be 0" );
#if LOG
      Log.Assert( this, removeCount != 0, "remove count cannot be 0" );
#endif

      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( startNode, 0, 0 );//index not important.
      GroupGeneratorNode parentGroup = startNode.Parent as GroupGeneratorNode;
      int i = 0;

      countRemoved = 0;

      do
      {
        GroupGeneratorNode group = nodeHelper.CurrentNode as GroupGeneratorNode;

        if( updateGroupNodeMappingCache )
        {
          m_groupNodeMappingCache.Remove( group.CollectionViewGroup );
        }

        Debug.Assert( group != null, "node to be removed must be a GroupGeneratorNode" );
#if LOG
        Log.Assert( this, group != null, "node to be removed must be a GroupGeneratorNode" );
#endif

        //add the total number of child to the count of items removed.
        countRemoved += group.ItemCount;

        i++;

        if( i < removeCount )
        {
          if( !nodeHelper.MoveToNext() )
          {
            //could not advance to the last item to be removed...

            throw new DataGridInternalException();
          }
        }
      }
      while( i < removeCount );

      //disconnect the node chain to be removed from the linked list.
      GeneratorNode previous = startNode.Previous;
      GeneratorNode next = nodeHelper.CurrentNode.Next;

      if( next != null )
      {
        next.Previous = previous;
      }

      if( previous != null )
      {
        previous.Next = next;
      }

      //if the first node removed was the first child of its parent
      if( ( parentGroup != null ) && ( parentGroup.Child == startNode ) )
      {
        //set the next in line after the chain to be removed as the first child
        parentGroup.Child = next;
      }

      //break the link between the chain and its same-level siblings.
      nodeHelper.CurrentNode.Next = null;
      startNode.Previous = null;

      //Here, I need a special handling case... If I remove the first group node, I need to set a new firstItem
      if( startNode == m_firstItem )
      {
        if( next != m_firstFooter )
        {
          m_firstItem = next;
        }
        else
        {
          m_firstItem = null;
        }

        if( m_startNode == startNode )
        {
          m_startNode = next;
        }
      }

      Debug.Assert( nodeHelper.CurrentNode is GroupGeneratorNode, "last node is not a GroupGeneratorNode" );
#if LOG
      Log.Assert( this, nodeHelper.CurrentNode is GroupGeneratorNode, "last node is not a GroupGeneratorNode" );
#endif

      return ( GroupGeneratorNode )nodeHelper.CurrentNode;
    }
 public HeadersFootersGeneratorNode(IList list, GeneratorNode parent)
     : base(list, parent)
 {
 }
    private GeneratorNode HandleSameLevelGroupAddition( GeneratorNode firstChild, out int countAdded, NotifyCollectionChangedEventArgs e )
    {

      Debug.Assert( ( ( firstChild.Parent == null ) || ( firstChild.Parent is GroupGeneratorNode ) ), "parent of the node should be a GroupGeneratorNode" );
#if LOG
      Log.Assert( this, ( ( firstChild.Parent == null ) || ( firstChild.Parent is GroupGeneratorNode ) ), "parent of the node should be a GroupGeneratorNode" );
#endif

      GeneratorNode newNodeChain = this.CreateGroupListFromCollection( e.NewItems, firstChild.Parent );

      countAdded = 0;
      if( newNodeChain != null )
      {
        int chainLength;
        GeneratorNodeHelper.EvaluateChain( newNodeChain, out countAdded, out chainLength );

        GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( firstChild, 0, 0 ); //do not care about index.

        //Advance to the first "Group" node (skip the GroupHEaders)
        while( !( nodeHelper.CurrentNode is GroupGeneratorNode ) )
        {
          if( !nodeHelper.MoveToNext() )
          {
            //if there are no items and no groups in the Group Node, then we will never find a GroupGeneratorNode...
            //However, the structure of the group/headers/footers/group headers/groups footers makes it so 
            //that inserting before the last item (footer/group footer) will place the group at the appropriate location.
            break;
          }
        }

        bool insertAfter = false;
        //If there is 0 group in the parent group, then this loop will exit without executing the control block once...
        for( int i = 0; i < e.NewStartingIndex; i++ )
        {
          if( !nodeHelper.MoveToNext() )
          {
            insertAfter = true;
          }
        }

        //if we are inserting past the end of the linked list level.
        if( insertAfter )
        {
          nodeHelper.InsertAfter( newNodeChain );
        }
        else
        {
          //we are inserting in the middle of the list
          nodeHelper.InsertBefore( newNodeChain );
        }


        //If the insertion point is the beginning, check that the node pointers are updated properly
        if( ( e.NewStartingIndex == 0 ) && ( ( firstChild.Parent == null ) ) )
        {
          if( m_startNode == m_firstItem )
          {
            m_startNode = newNodeChain;
          }
          m_firstItem = newNodeChain;
        }

      }

      return newNodeChain;
    }
示例#33
0
        //-------------
        // Methods

        internal virtual void CleanGeneratorNode()
        {
            this.Previous = null;
            this.Parent   = null;
            this.Next     = null;
        }
    private void HandleItemAddition( GeneratorNode node, NotifyCollectionChangedEventArgs e )
    {
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( node, 0, 0 ); //index not important for now.

      node.AdjustItemCount( e.NewItems.Count );

      ItemsGeneratorNode itemsNode = node as ItemsGeneratorNode;
      if( itemsNode != null )
      {
        itemsNode.AdjustLeafCount( e.NewItems.Count );
        this.OffsetDetails( itemsNode, e.NewStartingIndex, e.NewItems.Count );
      }

      //if the node is totally expanded
      if( node.IsComputedExpanded )
      {
        nodeHelper.ReverseCalculateIndex();

        //invalidate the indexes
        this.IncrementCurrentGenerationCount();

        int startIndex = nodeHelper.Index + e.NewStartingIndex;
        GeneratorPosition addGenPos = this.GeneratorPositionFromIndex( startIndex );

        //and send notification message
        this.SendAddEvent( addGenPos, startIndex, e.NewItems.Count );
      }
    }
示例#35
0
 internal GeneratorNode(GeneratorNode parent)
 {
     this.Parent = parent;
 }
    private GeneratorPosition FindFirstRealizedItemsForNode( GeneratorNode referenceNode )
    {
      GeneratorPosition retval = new GeneratorPosition( -1, 1 );
      int genPosCounter = -1;

      List<GeneratorNode> nodesAccepted = new List<GeneratorNode>();
      nodesAccepted.Add( referenceNode );

      //if there are details for the reference node
      ItemsGeneratorNode itemsNode = referenceNode as ItemsGeneratorNode;
      if( ( itemsNode != null ) && ( itemsNode.Details != null ) )
      {
        foreach( List<DetailGeneratorNode> details in itemsNode.Details.Values )
        {
          foreach( DetailGeneratorNode detailNode in details )
          {
            nodesAccepted.Add( detailNode );
          }
        }
      }

      for( int i = 0; i < m_genPosToNode.Count; i++ )
      {
        GeneratorNode node = m_genPosToNode[ i ];

        //For master/detail, I have to decouple the index to genPos relationship (because of detail rows, possibly messing up with generated items.
        genPosCounter++;

        //if the node currently observed is my reference node, get it's computed generator position
        if( nodesAccepted.Contains( node ) )
        {
          retval = new GeneratorPosition( genPosCounter, 0 );
          break;
        }
      }

      return retval;
    }
 internal NotifyCollectionChangedGeneratorNode(GeneratorNode parent)
     : base(parent)
 {
 }
    private void SetStatContext( DependencyObject container, GeneratorNode node )
    {
      GroupGeneratorNode parentGroup = node.Parent as GroupGeneratorNode;
      DataGridCollectionViewGroup cvg = null;

      if( parentGroup == null )
      {
        DataGridCollectionViewBase dataGridCollectionViewBase = null;

        if( m_dataGridContext != null )
        {
          dataGridCollectionViewBase = m_dataGridContext.ItemsSourceCollection as DataGridCollectionViewBase;
        }

        Debug.Assert( dataGridCollectionViewBase != null, "dataGridCollectionViewBase != null" );

        if( dataGridCollectionViewBase != null )
          cvg = dataGridCollectionViewBase.RootGroup as DataGridCollectionViewGroup;
      }
      else
      {
        cvg = parentGroup.CollectionViewGroup as DataGridCollectionViewGroup;
      }

      if( cvg != null )
        container.SetValue( DataGridControl.StatContextPropertyKey, cvg );
    }
 internal ItemsGeneratorNode(IList list, GeneratorNode parent)
     : base(list, parent)
 {
 }