Пример #1
0
        public override object GetAt(int index)
        {
            if (index < 0)
            {
                return(null);
            }

            if ((m_detailsMapping == null) ||
                (m_detailsMapping.Count == 0))
            {
                //If there are no details, call base (quicker)
                return(base.GetAt(index));
            }

            int masterIndex;
            int detailIndex;
            int detailNodeIndex;
            DetailGeneratorNode detailNode = this.GetDetailNodeForIndex(index, out masterIndex, out detailIndex, out detailNodeIndex);

            if (detailNode == null)
            {
                return(this.Items[masterIndex]);
            }

            return(detailNode.DetailGenerator.ItemFromIndex(detailIndex));
        }
Пример #2
0
        public DetailGeneratorNode GetDetailNodeForIndex(int targetIndex, out int masterIndex, out int detailIndex, out int detailNodeIndex)
        {
            masterIndex     = -1;
            detailIndex     = -1;
            detailNodeIndex = -1;

            if ((m_detailsMapping == null) ||
                (m_detailsMapping.Count == 0))
            {
                masterIndex = targetIndex;
                return(null);
            }

            int runningDetailCount = 0;

            foreach (KeyValuePair <int, List <DetailGeneratorNode> > pair in m_detailsMapping)
            {
                List <DetailGeneratorNode> detailNodeList = pair.Value;
                int currentIndex = pair.Key;

                int runningIndex = (currentIndex + runningDetailCount);

                if (targetIndex < runningIndex)
                {
                    masterIndex = targetIndex - runningDetailCount;
                    return(null);
                }

                if (runningIndex == targetIndex)
                {
                    masterIndex = currentIndex;
                    return(null);
                }

                int count = detailNodeList.Count;
                for (int i = 0; i < count; i++)
                {
                    DetailGeneratorNode detailNode = detailNodeList[i];
                    int detailItemCount            = detailNode.ItemCount;

                    if (targetIndex <= (runningIndex + detailItemCount))
                    {
                        masterIndex     = currentIndex;
                        detailIndex     = targetIndex - runningIndex - 1;
                        detailNodeIndex = i;
                        return(detailNode);
                    }
                    else
                    {
                        runningDetailCount += detailItemCount;
                        runningIndex       += detailItemCount;
                    }
                }
            }

            masterIndex = targetIndex - runningDetailCount;
            return(null);
        }
Пример #3
0
        public override int IndexOf(object item)
        {
            if ((m_detailsMapping == null) ||
                (m_detailsMapping.Count == 0))
            {
                return(base.IndexOf(item));
            }

            int tmpIndex = this.Items.IndexOf(item);

            if (tmpIndex != -1)
            {
                return(tmpIndex + this.CountDetailsBeforeDataIndex(tmpIndex));
            }

            int runningDetailCount = 0;

            foreach (KeyValuePair <int, List <DetailGeneratorNode> > pair in m_detailsMapping)
            {
                List <DetailGeneratorNode> detailNodeList = pair.Value;

                int currentIndex = pair.Key;
                int runningIndex = (currentIndex + runningDetailCount);

                int count = detailNodeList.Count;
                for (int i = 0; i < count; i++)
                {
                    DetailGeneratorNode detailNode = detailNodeList[i];
                    int detailIndex = detailNode.DetailGenerator.IndexFromItem(item);

                    if (detailIndex > -1)
                    {
                        return(runningIndex + detailIndex + 1);
                    }

                    int detailItemCount = detailNode.ItemCount;

                    runningDetailCount += detailItemCount;
                    runningIndex       += detailItemCount;
                }
            }

            return(-1);
        }
    private int FindGeneratorIndexForNode( DetailGeneratorNode referenceNode, int offset )
    {
      int offsetCounter = -1;

      for( int i = 0; i < m_genPosToNode.Count; i++ )
      {
        GeneratorNode node = m_genPosToNode[ i ];
        if( node == referenceNode )
        {
          offsetCounter++;
          if( offsetCounter == offset )
          {
            return i;
          }
        }
      }

      return -1;
    }
    private GeneratorPosition ConvertDetailGeneratorPosition( GeneratorPosition referencePosition, object masterItem, DetailGeneratorNode detailNode, out int globalIndex )
    {
      //If the requested generator position map past at least one generated item from the detail generator, then the job is easy...
      if( referencePosition.Index >= 0 )
      {
        int generatorIndex = this.FindGeneratorIndexForNode( detailNode, referencePosition.Index );

        // Ensure to return the globalIndex as -1
        // if the generator index is not found for
        // a DetailNode. This can occur if a Detail
        // is filtered out via AutoFiltering.
        globalIndex = ( generatorIndex > -1 )
          ? m_genPosToIndex[ generatorIndex ]
          : globalIndex = -1;

        return new GeneratorPosition( generatorIndex, referencePosition.Offset );
      }
      else
      {
        //This means the GeneratorPosition returned by the DetailGenerator is "before" any generated item from the detail generator.
        //I need more complex detection of the GeneratorPosition.

        // First - Get the Index of the MasterItem
        int masterIndex = this.IndexFromItem( masterItem );

        //Second - Get the DetailGenerator's Index for the DetailGenerator's GenPos
        int detailGeneratorIndex = detailNode.DetailGenerator.IndexFromGeneratorPosition( referencePosition );

        globalIndex = masterIndex + detailGeneratorIndex + 1;

        // Finally - Have the Master Generator compute the GeneratorPosition from the sum of both
        return this.GeneratorPositionFromIndex( globalIndex );
      }
    }
    private void HandleDetailReset( object masterItem, DetailGeneratorNode detailNode )
    {
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );
      int masterIndex = nodeHelper.FindItem( masterItem );

      // -1 means either taht the master item is below a collapsed group node, or that the item does not exists, validate.
      if( masterIndex == -1 )
      {
        nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );
        if( !nodeHelper.Contains( masterItem ) )
          throw new DataGridInternalException();
      }

      ItemsGeneratorNode masterNode = nodeHelper.CurrentNode as ItemsGeneratorNode;

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

      //start index will be ignored later on if the masterIndex is -1!!
      int startIndex = nodeHelper.Index + masterNode.IndexOf( masterItem ) + 1; //details start a master index + 1

      List<DetailGeneratorNode> detailsForMaster = null;

      //edge case, it is possible to receive a Reset from Floating details!
      if( masterNode.Details == null )
      {
        //check for floating details, if not present, throw, this is an abnormal case.
        if( !m_floatingDetails.Contains( masterItem ) )
        {
          throw new DataGridInternalException();
        }
      }
      else
      {
        masterNode.Details.TryGetValue( masterNode.Items.IndexOf( masterItem ), out detailsForMaster );

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

      if( detailsForMaster != null )
      {
        //this is required to ensure that if the details that resets is not the first one, the index is calculated appropriatly.
        foreach( DetailGeneratorNode node in detailsForMaster )
        {
          if( node == detailNode )
          {
            break;
          }
          else
          {
            startIndex += node.ItemCount;
          }
        }

        //if there were 'items' in the detail node, process the remove of them
        int oldDetailCount = detailNode.ItemCount;
        if( oldDetailCount > 0 )
        {
          int endIndex = startIndex + oldDetailCount - 1; //last detail index

          GeneratorPosition removeGenPos = ( masterIndex != -1 )
            ? this.GeneratorPositionFromIndex( startIndex )
            : new GeneratorPosition( -1, 1 );

          int genRemCount = 0;

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

          //this has no uses if the masterIndex is -1 ( collapsed master item )
          if( masterIndex != -1 )
          {
            genRemCount = this.RemoveGeneratedItems( startIndex, endIndex, removedContainers );
          }

          masterNode.AdjustItemCount( -oldDetailCount );

          this.IncrementCurrentGenerationCount();

          //this has no uses if the masterIndex is -1 ( collapsed master item )
          if( masterIndex != -1 )
          {
            this.SendRemoveEvent( removeGenPos, masterIndex + 1, oldDetailCount, genRemCount, removedContainers );
          }
        }

        detailNode.UpdateItemCount();

        int newDetailCount = detailNode.ItemCount;
        if( newDetailCount > 0 )
        {
          GeneratorPosition addGenPos = new GeneratorPosition( -1, 1 );

          //this has no uses if the masterIndex is -1 ( collapsed master item )
          if( masterIndex != -1 )
          {
            addGenPos = this.GeneratorPositionFromIndex( startIndex );
          }

          masterNode.AdjustItemCount( newDetailCount );

          this.IncrementCurrentGenerationCount();

          //this has no uses if the masterIndex is -1 ( collapsed master item )
          if( masterIndex != -1 )
          {
            this.SendAddEvent( addGenPos, masterIndex + 1, newDetailCount );
          }
        }
      }
    }
    private void HandleDetailMoveRemove( object masterItem, DetailGeneratorNode detailNode, CustomGeneratorChangedEventArgs e )
    {
      GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );
      int masterIndex = nodeHelper.FindItem( masterItem );

      //If the masterItem is part of an ItemsGeneratorNode which is below a collapsed group, masterIndex will be -1
      if( masterIndex == -1 )
      {
        //in that case, I need to determine the appropriate masterNode another way
        nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );
        if( !nodeHelper.Contains( masterItem ) )
          throw new DataGridInternalException();
      }

      ItemsGeneratorNode masterNode = nodeHelper.CurrentNode as ItemsGeneratorNode;

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

      int globalIndex = -1;
      GeneratorPosition convertedGeneratorPosition = ( masterIndex != -1 ) ? this.ConvertDetailGeneratorPosition( e.OldPosition, masterItem, detailNode, out globalIndex ) : new GeneratorPosition( -1, 1 );

      if( masterIndex != -1 )
      {
        this.RemoveDetailContainers( convertedGeneratorPosition, e.ItemUICount );
      }

      if( e.Action == NotifyCollectionChangedAction.Remove )
      {
        masterNode.AdjustItemCount( -e.ItemCount );

        detailNode.UpdateItemCount();
      }

      this.IncrementCurrentGenerationCount();

      if( masterIndex != -1 )
      {
        this.SendRemoveEvent( convertedGeneratorPosition, globalIndex, e.ItemCount, e.ItemUICount, e.RemovedContainers );
      }
    }
    private void CleanDetailNode( DetailGeneratorNode detailNode )
    {
#if LOG
      Log.Start( this, "CleanDetailNode - DN" + detailNode.GetHashCode().ToString() );
#endif

      m_dataGridControl.SelectionChangerManager.Begin();

      try
      {
        m_dataGridControl.SelectionChangerManager.UnselectAllItems( detailNode.DetailContext );
        m_dataGridControl.SelectionChangerManager.UnselectAllCells( detailNode.DetailContext );
      }
      finally
      {
        m_dataGridControl.SelectionChangerManager.End( false, false, false );
      }

      m_dataGridControl.SaveDataGridContextState( detailNode.DetailContext, true, int.MaxValue );

      CustomItemContainerGenerator generator = detailNode.DetailGenerator;

      detailNode.CleanGeneratorNode();

      DetailsChangedEventManager.RemoveListener( generator, this );
      generator.ItemsChanged -= HandleDetailGeneratorContentChanged;
      generator.ContainersRemoved -= OnDetailContainersRemoved;
      generator.SetGenPosToIndexUpdateInhibiter( null );

#if LOG
      Log.End( this, "CleanDetailNode - DN" + detailNode.GetHashCode().ToString() );
#endif
    }
    private int FindGlobalIndexForDetailNode( DetailGeneratorNode detailNode )
    {
      int retval = -1;

      //first thing, loop through the details for the 
      foreach( KeyValuePair<object, List<DetailGeneratorNode>> masterItemToDetails in m_masterToDetails )
      {
        //in each master to details entry, try to find the detail node passed
        int detailIndex = masterItemToDetails.Value.IndexOf( detailNode );
        if( detailIndex != -1 )
        {
          //if the desired detailNode is present for this master item... then evaluate it...
          int detailNodeOffset = 0;
          for( int i = 0; i < detailIndex; i++ )
          {
            detailNodeOffset += masterItemToDetails.Value[ i ].ItemCount - 1;
          }

          int index = m_genPosToItem.IndexOf( masterItemToDetails.Key );
          int masterItemIndex;

          if( index > -1 )
          {
            masterItemIndex = m_genPosToIndex[ index ];
          }
          else
          {
            GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 );
            masterItemIndex = nodeHelper.FindItem( masterItemToDetails.Key );
          }

          if( masterItemIndex == -1 )
            throw new DataGridInternalException();

          retval = detailNodeOffset + masterItemIndex + detailIndex + 1;

          //leave the top level loop
          break;
        }
      }

      return retval;
    }
    private List<StickyContainerGenerated> GenerateStickyFootersForDetail(
      DependencyObject container,
      DetailGeneratorNode detailNode,
      bool areFootersSticky,
      bool areGroupFootersSticky )
    {
      List<StickyContainerGenerated> generatedStickyContainers =
        detailNode.DetailGenerator.GenerateStickyFooters( container, areFootersSticky, areGroupFootersSticky );

      int detailIndex = this.FindGlobalIndexForDetailNode( detailNode );

      int count = generatedStickyContainers.Count;
      for( int i = 0; i < count; i++ )
      {
        StickyContainerGenerated stickyContainer = generatedStickyContainers[ i ];
        int detailItemIndex = stickyContainer.Index + detailIndex;

        //if the container was just realized, ensure to add it to the lists maintaining the generated items.
        if( stickyContainer.IsNewlyRealized )
        {
          int insertionIndex = this.FindInsertionPoint( detailItemIndex );

          m_genPosToIndex.Insert( insertionIndex, detailItemIndex );
          m_genPosToItem.Insert( insertionIndex, CustomItemContainerGenerator.GetDataItemProperty( stickyContainer.StickyContainer ) );
          m_genPosToContainer.Insert( insertionIndex, stickyContainer.StickyContainer );
          m_genPosToNode.Insert( insertionIndex, detailNode );
        }

        generatedStickyContainers[ i ] = new StickyContainerGenerated(
          stickyContainer.StickyContainer,
          detailItemIndex,
          stickyContainer.IsNewlyRealized );
      }

      return generatedStickyContainers;
    }
Пример #11
0
        private static void ProcessItemsNodeBlockVisit(
            ItemsGeneratorNode itemsNode,
            DataGridContext sourceContext,
            int minIndex,
            int maxIndex,
            IDataGridContextVisitor visitor,
            DataGridContextVisitorType visitorType,
            bool visitDetails,
            bool containsDetails,
            int sourceDataItemIndex,
            ref int startSourceDataItemIndex,
            ref int endSourceDataItemIndex,
            ref bool stopVisit)
        {
            if (maxIndex < minIndex)
            {
                return;
            }

            int runningIndex = minIndex;

            sourceDataItemIndex += minIndex - itemsNode.CountDetailsBeforeGlobalIndex(minIndex);

            if (!containsDetails)
            {
                // If we contains no detail, we take a quick way out of it.
                if (startSourceDataItemIndex == -1)
                {
                    startSourceDataItemIndex = sourceDataItemIndex;
                }
                else
                {
                    if ((endSourceDataItemIndex + 1) != sourceDataItemIndex)
                    {
                        visitor.Visit(sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit);

                        if (stopVisit)
                        {
                            return;
                        }

                        startSourceDataItemIndex = sourceDataItemIndex;
                    }
                }

                endSourceDataItemIndex = sourceDataItemIndex + Math.Min(maxIndex - minIndex, itemsNode.Items.Count - 1);
                return;
            }

            int masterIndex;
            int detailStartIndex;
            int detailNodeIndex;

            while (runningIndex <= maxIndex)
            {
                DetailGeneratorNode detailNode = itemsNode.GetDetailNodeForIndex(runningIndex, out masterIndex, out detailStartIndex, out detailNodeIndex);

                if (detailNode != null)
                {
                    int detailEndIndex = Math.Min(detailNode.ItemCount - 1, detailStartIndex + (maxIndex - runningIndex));
                    sourceDataItemIndex -= detailStartIndex;
                    bool visitWasStopped;

                    (( IDataGridContextVisitable )detailNode.DetailGenerator).AcceptVisitor(
                        detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped);

                    stopVisit = stopVisit || visitWasStopped;

                    if (stopVisit)
                    {
                        break;
                    }

                    runningIndex += detailNode.ItemCount - detailStartIndex - 1;
                }
                else
                {
                    // set the first data index that will be visited for that items block
                    if (startSourceDataItemIndex == -1)
                    {
                        startSourceDataItemIndex = sourceDataItemIndex;
                        endSourceDataItemIndex   = sourceDataItemIndex;
                    }
                    else
                    {
                        if ((endSourceDataItemIndex + 1) != sourceDataItemIndex)
                        {
                            visitor.Visit(sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit);

                            if (stopVisit)
                            {
                                break;
                            }

                            startSourceDataItemIndex = sourceDataItemIndex;
                        }

                        endSourceDataItemIndex = sourceDataItemIndex;
                    }

                    sourceDataItemIndex++;
                }

                runningIndex++;
            }
        }
Пример #12
0
        private static void ProcessItemsNodeVisit(
            ItemsGeneratorNode itemsNode,
            DataGridContext sourceContext,
            int minIndex,
            int maxIndex,
            IDataGridContextVisitor visitor,
            DataGridContextVisitorType visitorType,
            bool visitDetails,
            int sourceDataItemIndex,
            ref bool stopVisit)
        {
            int runningIndex = minIndex;

            sourceDataItemIndex += minIndex;

            int masterIndex;
            int detailStartIndex;
            int detailNodeIndex;

            while (runningIndex <= maxIndex)
            {
                DetailGeneratorNode detailNode = itemsNode.GetDetailNodeForIndex(runningIndex, out masterIndex, out detailStartIndex, out detailNodeIndex);

                if (detailNode != null)
                {
                    int detailEndIndex = Math.Min(detailNode.ItemCount - 1, detailStartIndex + (maxIndex - runningIndex));
                    sourceDataItemIndex -= detailStartIndex;

                    if (visitDetails)
                    {
                        bool visitWasStopped;

                        (( IDataGridContextVisitable )detailNode.DetailGenerator).AcceptVisitor(
                            detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped);

                        stopVisit |= visitWasStopped;

                        if (stopVisit)
                        {
                            break;
                        }

                        runningIndex += detailNode.ItemCount - detailStartIndex - 1;
                    }
                }
                else
                {
                    if ((visitorType & DataGridContextVisitorType.Items) == DataGridContextVisitorType.Items)
                    {
                        object dataItem = itemsNode.GetAt(runningIndex);
                        visitor.Visit(sourceContext, sourceDataItemIndex, dataItem, ref stopVisit);

                        if (stopVisit)
                        {
                            break;
                        }
                    }

                    sourceDataItemIndex++;
                }

                runningIndex++;
            }
        }