コード例 #1
0
    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;
    }
コード例 #2
0
    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();
    }
コード例 #3
0
    private GeneratorNode SetupInitialItemsNodes( out int addCount )
    {
      //TODO ( case 117275 ): Check the amount of time this is executed for a single grid being populated!
      GeneratorNode newItemNode = null;

      addCount = 0;

      this.RefreshGroupsCollection();

      //this function should only be called when the m_firstItem is null.
      if( m_groupsCollection != null )
      {
        newItemNode = this.CreateGroupListFromCollection( m_groupsCollection, null );
      }
      else
      {
        newItemNode = this.CreateStandaloneItemsNode();
      }

      //if the node is non-null, then that's because there was items in the collection
      if( newItemNode != null )
      {
        m_firstItem = newItemNode;

        int chainLength;
        GeneratorNodeHelper.EvaluateChain( m_firstItem, out addCount, out chainLength );

        //find the appropriate point to inject the Items nodes...
        if( m_startNode != null )
        {
          //if there is a footer node, then the insertion point is just before the footer node (if there is anything before!)
          if( m_firstFooter != null )
          {
            GeneratorNode originalPrevious = m_firstFooter.Previous;
            GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_firstFooter, 0, 0 ); //do not care about index!

            nodeHelper.InsertBefore( m_firstItem );

            if( originalPrevious == null ) //that means that the first footer is the first item
            {
              m_startNode = newItemNode;
            }
          }
          else if( m_firstHeader != null ) //if there is no footer but some headers, add it at the end.
          {
            GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_firstHeader, 0, 0 ); //do not care about index!

            nodeHelper.MoveToEnd();
            nodeHelper.InsertAfter( m_firstItem );
          }
          else
          {
            throw new DataGridInternalException(); //this case should not be possible: no header, no footers but there is a startNode
          }
        }
        else
        {
          m_startNode = m_firstItem;
#if LOG
          Log.WriteLine( this, "SetupInitialItemsNodes - new tree" );
#endif
        }
      }

      return newItemNode;
    }
コード例 #4
0
    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;
    }
コード例 #5
0
    private void UpdateFooters( IList footers )
    {

      //if there was no header prior this udpate.
      if( m_firstFooter == null )
      {
        //create the node(s) that would contain the footers
        m_firstFooter = this.CreateFooters( footers );

        //if there are no footers, then the m_firstFooter will remain null
        if( m_firstFooter != null )
        {
          int count;
          int chainLength;
          GeneratorNodeHelper.EvaluateChain( m_firstFooter, out count, out chainLength );

          //if there was items present in the linked list.
          if( m_startNode != null )
          {
            //since we called ClearFooters earlier, I can just go at the end of the list of items
            GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );

            nodeHelper.MoveToEnd();
            nodeHelper.InsertAfter( m_firstFooter );
          }
          else
          {
            m_startNode = m_firstFooter;
#if LOG
            Log.WriteLine( this, "UpdateFooters - new tree" );
#endif
          }
        }
      }

      //If the m_firstHeader is not NULL, then there is nothing to do, since the Header node contains an  observable collection
      //which we monitor otherwise.
    }