/// <summary>
        /// Revirtualize items that are no longer visible
        /// </summary>
        /// <param name="minDesiredGenerated">first item index that should be visible</param>
        /// <param name="maxDesiredGenerated">last item index that should be visible</param>
        private void CleanUpItems(int minDesiredGenerated, int maxDesiredGenerated)
        {
            UIElementCollection     children  = this.InternalChildren;
            IItemContainerGenerator generator = this.ItemContainerGenerator;

            int itemCount      = GetItemCount();
            int childrenPerRow = CalculateChildrenPerRow(this.extent);

            if (minDesiredGenerated - 2 * childrenPerRow > 0)
            {
                minDesiredGenerated -= 2 * childrenPerRow;
            }
            if (maxDesiredGenerated + 2 * childrenPerRow < itemCount)
            {
                maxDesiredGenerated += 2 * childrenPerRow;
            }

            for (int i = children.Count - 1; i >= 0; i += -1)
            {
                GeneratorPosition childGeneratorPos = new GeneratorPosition(i, 0);
                int itemIndex = generator.IndexFromGeneratorPosition(childGeneratorPos);
                if ((itemIndex > 2 * childrenPerRow - 1 && itemIndex < minDesiredGenerated) ||
                    (itemIndex < itemCount - 2 * childrenPerRow - 1 && itemIndex > maxDesiredGenerated))
                {
                    generator.Remove(childGeneratorPos, 1);
                    RemoveInternalChildRange(i, 1);
                }
            }
        }
Exemple #2
0
        private void AddChildren(GeneratorPosition pos, int itemCount)
        {
            IItemContainerGenerator generator = (IItemContainerGenerator)Generator;

            using (generator.StartAt(pos, GeneratorDirection.Forward))
            {
                for (int i = 0; i < itemCount; i++)
                {
                    UIElement e = generator.GenerateNext() as UIElement;
                    if (e != null)
                    {
                        _generatedItemsCollection.Insert(pos.Index + 1 + i, e);
                        generator.PrepareItemContainer(e);
                    }
                    else
                    {
                        ItemContainerGenerator icg = Generator as ItemContainerGenerator;
                        if (icg != null)
                        {
                            icg.Verify();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Arrange the children
        /// </summary>
        /// <param name="finalSize">Size available</param>
        /// <returns>Size used</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            IItemContainerGenerator generator = this.ItemContainerGenerator;

            UpdateScrollInfo(finalSize);

            for (int i = 0; i < this.Children.Count; i++)
            {
                UIElement child = this.Children[i];

                // Map the child offset to an item offset
                int itemIndex = generator.IndexFromGeneratorPosition(new GeneratorPosition(i, 0));

                ArrangeChild(itemIndex, child, finalSize);

                var listBoxItem = child as ListBoxItem;
                if (listBoxItem != null)
                {
                    listBoxItem.Selected -= ListBoxItemSelected;
                    listBoxItem.Selected += ListBoxItemSelected;
                }
            }

            return(finalSize);
        }
Exemple #4
0
        protected override void OnIsItemsHostChanged(bool oldIsItemsHost, bool newIsItemsHost)
        {
            base.OnIsItemsHostChanged(oldIsItemsHost, newIsItemsHost);

            if (newIsItemsHost)
            {
                var owner = this.TreeGrid;
                if (owner != null)
                {
                    IItemContainerGenerator itemContainerGenerator = owner.ItemContainerGenerator;
                    if (itemContainerGenerator != null && itemContainerGenerator == itemContainerGenerator.GetItemContainerGeneratorForPanel(this))
                    {
                        owner.RowsPanel = this;
                        return;
                    }
                }
            }
            else
            {
                if (this._owner != null && this._owner.RowsPanel == this)
                {
                    this._owner.RowsPanel = null;
                }
                this._owner = null;
            }
        }
Exemple #5
0
        public void GridRowNumberConverter_Convert_WhenValidRow_ReturnsRowIndex()
        {
            var      converter = new GridRowNumberConverter();
            DataGrid dataGrid  = new DataGrid {
                AutoGenerateColumns = true
            };
            var itemsSource = new List <string> {
                "Item 1 ", "Item 2"
            };

            dataGrid.ItemsSource  = itemsSource;
            dataGrid.SelectedItem = itemsSource[0];
            IItemContainerGenerator generator = dataGrid.ItemContainerGenerator;
            var position = generator.GeneratorPositionFromIndex(0);

            using (generator.StartAt(position, GeneratorDirection.Forward, true))
            {
                foreach (object o in dataGrid.Items)
                {
                    DependencyObject dp = generator.GenerateNext();
                    generator.PrepareItemContainer(dp);
                }
            }
            var row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(dataGrid.SelectedItem);
            //------------Execute Test---------------------------
            var result = converter.Convert(row, typeof(string), null, CultureInfo.CurrentCulture);

            //------------Assert Results-------------------------
            Assert.AreEqual(1, result);
        }
        protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
        {
            switch (args.Action)
            {
            case NotifyCollectionChangedAction.Remove:
            case NotifyCollectionChangedAction.Replace:
                RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
                break;

            case NotifyCollectionChangedAction.Move:
                if (args.Position.Index < 0)
                {
                    InvalidateMeasure();
                    ScrollOwner?.InvalidateScrollInfo();
                    SetVerticalOffset(0);
                }
                else
                {
                    RemoveInternalChildRange(args.OldPosition.Index, args.ItemUICount);
                }
                break;

            case NotifyCollectionChangedAction.Reset:
                itemsControl = ItemsControl.GetItemsOwner(this);
                generator    = (IRecyclingItemContainerGenerator)ItemContainerGenerator;
                InvalidateMeasure();
                ScrollOwner?.InvalidateScrollInfo();
                SetVerticalOffset(0);
                break;
            }
        }
Exemple #7
0
        private void ReplaceChildren(GeneratorPosition pos, int itemCount, int containerCount)
        {
            Debug.Assert(itemCount == containerCount, "ToolBarPanel expects Replace to affect only realized containers");

            IItemContainerGenerator generator = (IItemContainerGenerator)Generator;

            using (generator.StartAt(pos, GeneratorDirection.Forward, true))
            {
                for (int i = 0; i < itemCount; i++)
                {
                    bool      isNewlyRealized;
                    UIElement e = generator.GenerateNext(out isNewlyRealized) as UIElement;

                    Debug.Assert(e != null && !isNewlyRealized, "ToolBarPanel expects Replace to affect only realized containers");
                    if (e != null && !isNewlyRealized)
                    {
                        RemoveChild(_generatedItemsCollection[pos.Index + i]);
                        _generatedItemsCollection[pos.Index + i] = e;
                        generator.PrepareItemContainer(e);
                    }
                    else
                    {
                        ItemContainerGenerator icg = Generator as ItemContainerGenerator;
                        if (icg != null)
                        {
                            icg.Verify();
                        }
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        ///     This method is invoked when the IsItemsHost property changes.
        /// </summary>
        /// <param name="oldIsItemsHost">The old value of the IsItemsHost property.</param>
        /// <param name="newIsItemsHost">The new value of the IsItemsHost property.</param>
        protected override void OnIsItemsHostChanged(bool oldIsItemsHost, bool newIsItemsHost)
        {
            base.OnIsItemsHostChanged(oldIsItemsHost, newIsItemsHost);

            if (newIsItemsHost)
            {
                RibbonContextualTabGroupItemsControl groupHeaderItemsControl = ParentItemsControl;
                if (groupHeaderItemsControl != null)
                {
                    IItemContainerGenerator generator = groupHeaderItemsControl.ItemContainerGenerator as IItemContainerGenerator;
                    if (generator != null && generator.GetItemContainerGeneratorForPanel(this) == generator)
                    {
                        groupHeaderItemsControl.InternalItemsHost = this;
                    }
                }
            }
            else
            {
                RibbonContextualTabGroupItemsControl groupHeaderItemsControl = ParentItemsControl;
                if (groupHeaderItemsControl != null && groupHeaderItemsControl.InternalItemsHost == this)
                {
                    groupHeaderItemsControl.InternalItemsHost = null;
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Measure the children
        /// </summary>
        /// <param name="availableSize">Size available</param>
        /// <returns>Size desired</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            UpdateScrollInfo(availableSize);

            // Figure out range that's visible based on layout algorithm
            int firstVisibleItemIndex, lastVisibleItemIndex;

            GetVisibleRange(out firstVisibleItemIndex, out lastVisibleItemIndex);

            // We need to access InternalChildren before the generator to work around a bug
            UIElementCollection     children  = this.InternalChildren;
            IItemContainerGenerator generator = this.ItemContainerGenerator;

            // Get the generator position of the first visible data item
            GeneratorPosition startPos = generator.GeneratorPositionFromIndex(firstVisibleItemIndex);

            // Get index where we'd insert the child for this position. If the item is realized
            // (position.Offset == 0), it's just position.Index, otherwise we have to add one to
            // insert after the corresponding child
            int childIndex = (startPos.Offset == 0) ? startPos.Index : startPos.Index + 1;

            using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
            {
                for (int itemIndex = firstVisibleItemIndex; itemIndex <= lastVisibleItemIndex; ++itemIndex, ++childIndex)
                {
                    bool newlyRealized;

                    // Get or create the child
                    UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;

                    if (newlyRealized)
                    {
                        // Figure out if we need to insert the child at the end or somewhere in the middle
                        if (childIndex >= children.Count)
                        {
                            base.AddInternalChild(child);
                        }
                        else
                        {
                            base.InsertInternalChild(childIndex, child);
                        }
                        generator.PrepareItemContainer(child);
                    }
                    else
                    {
                        // The child has already been created, let's be sure it's in the right spot
                        Debug.Assert(child == children[childIndex], "Wrong child was generated");
                    }

                    // Measurements will depend on layout algorithm
                    child.Measure(ChildSize);
                }
            }

            // Note: this could be deferred to idle time for efficiency
            CleanUpItems(firstVisibleItemIndex, lastVisibleItemIndex);

            return(availableSize);//base.MeasureOverride(availableSize);
        }
 protected override void OnInitialized(EventArgs e)
 {
     base.OnInitialized(e);
     this.itemsControl = ItemsControl.GetItemsOwner(this);
     this.children     = this.InternalChildren;
     this.generator    = this.ItemContainerGenerator;
     this.SizeChanged += new SizeChangedEventHandler(this.Resizing);
 }
Exemple #11
0
        private GeneratorPosition IndexToGeneratorPositionForStart(int index, out int childIndex)
        {
            IItemContainerGenerator generator = this.ItemContainerGenerator;
            GeneratorPosition       position  = (generator != null) ? generator.GeneratorPositionFromIndex(index) : new GeneratorPosition(-1, index + 1);

            childIndex = (position.Offset == 0) ? position.Index : (position.Index + 1);
            return(position);
        }
Exemple #12
0
 protected override void OnInitialized(EventArgs e)
 {
     base.OnInitialized(e);
     _itemsControl = ItemsControl.GetItemsOwner(this);
     _children     = InternalChildren;
     _generator    = ItemContainerGenerator;
     SizeChanged  += Resizing;
 }
            public ChildGenerator(VirtualizingWrapPanel owner)
            {
                this.owner = owner;

                var childrenCount = owner.InternalChildren.Count;

                this.generator = owner.ItemContainerGenerator;
            }
Exemple #14
0
 private void Cleanup(IItemContainerGenerator generator, IEnumerable <UIElement> children)
 {
     foreach (var child in children)
     {
         var childIndex = InternalChildren.IndexOf(child);
         VirtualizeContainer(generator, child, childIndex);
     }
 }
            /// <summary>
            /// <see cref="ChildGenerator"/> の新しいインスタンスを生成する。
            /// </summary>
            /// <param name="owner">アイテムを生成する対象の <see cref="VirtualizingStackPanel"/>。</param>
            public ChildGenerator(VirtualizingStackPanel owner)
            {
                _owner = owner;

                // ItemContainerGenerator 取得前に InternalChildren にアクセスしないと null になる
                var childrenCount = owner.InternalChildren.Count;

                _generator = owner.ItemContainerGenerator;
            }
Exemple #16
0
        private void Realize(UIElementCollection children, IItemContainerGenerator generator)
        {
            /*********************** 代码块解释 *********************************
             *
             * 虚拟化模式下,为了保证编辑状态的焦点不会丢失,生成单元格过程中不再移除已经之前生成好的单元格。
             * 所有已经生成好的单元格都会被 generator 存储起来,
             * 而以下过程只是修改 InternalChildren,即可视树中的元素:
             * 一开始,先把所有可视树子节点移除,然后不论是否刚生成的单元格,都直接加入到可视树中。
             *
             **********************************************************************/

            foreach (var child in children)
            {
                var cell = child as TreeGridCell;
                if (cell == null)
                {
                    break;
                }

                cell.VisibleOnVirtualizing = false;
            }

            this.RemoveInternalChildRange(0, children.Count);

            // 获取第一个可视元素位置信息
            var start = generator.GeneratorPositionFromIndex(this._from);

            using (generator.StartAt(start, GeneratorDirection.Forward, true))
            {
                for (int i = this._from; i <= this._to; i++)
                {
                    bool isNewlyRealized;
                    var  container = generator.GenerateNext(out isNewlyRealized) as UIElement;

                    this.AddInternalChild(container);

                    var cell = container as TreeGridCell;
                    if (cell != null)
                    {
                        cell.VisibleOnVirtualizing = true;
                    }

                    if (isNewlyRealized)
                    {
                        generator.PrepareItemContainer(container);
                    }
                    else
                    {
                        //正在编辑的有焦点的控件,需要还原其焦点。
                        if (cell != null)
                        {
                            this._cellsPresenter.RestoreEditingCellFocus(cell);
                        }
                    }
                }
            }
        }
            /// <summary>
            /// <see cref="ChildGenerator"/> の新しいインスタンスを生成する。
            /// </summary>
            /// <param name="owner">アイテムを生成する対象の <see cref="VirtualizingWrapPanel"/>。</param>
            public ChildGenerator(VirtualizingWrapPanel owner)
            {
                this.owner = owner;

                // ItemContainerGenerator 取得前に InternalChildren にアクセスしないと null になる
                var childrenCount = owner.InternalChildren.Count;

                this.generator = owner.ItemContainerGenerator;
            }
Exemple #18
0
            /// <summary>
            /// Initializes a new instance of the <see cref="ChildGenerator" /> class.
            /// </summary>
            /// <param name="owner"> the target of generating the item<see cref="VirtualizingWrapPanel"/>.</param>
            public ChildGenerator(VirtualizingWrapPanel owner)
            {
                this.owner = owner;

                // ItemContainerGenerator it gets null unless you access InternalChildren before getting it
                var childrenCount = owner.InternalChildren.Count;

                generator = owner.ItemContainerGenerator;
            }
Exemple #19
0
        protected override Size MeasureOverride(Size availableSize)
        {
            var          desiredSize = new Size();
            ItemsControl parent      = ItemsControl.GetItemsOwner(this);
            int          count       = parent != null && parent.HasItems ? parent.Items.Count : 0;

            // Next line needed otherwise ItemContainerGenerator is null (bug in WinFX ?)
            UIElementCollection     children  = InternalChildren;
            IItemContainerGenerator generator = ItemContainerGenerator;

            if (count == 0)
            {
                generator.RemoveAll();
                if (children.Count > 0)
                {
                    RemoveInternalChildRange(0, children.Count);
                }
                return(desiredSize);
            }

            // Get the generator position of the first visible data item
            GeneratorPosition startPos = generator.GeneratorPositionFromIndex(count - 1);

            using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
            {
                bool newlyRealized;
                // Get or create the child
                var child = generator.GenerateNext(out newlyRealized) as UIElement;

                if (child != null)
                {
                    if (newlyRealized)
                    {
                        AddInternalChild(child);
                        generator.PrepareItemContainer(child);
                    }
                    child.Measure(availableSize);
                    desiredSize = child.DesiredSize;
                }
            }

            // Remove all other items than the top one
            for (int i = children.Count - 1; i >= 0; i--)
            {
                var childGeneratorPos = new GeneratorPosition(i, 0);
                int itemIndex         = generator.IndexFromGeneratorPosition(childGeneratorPos);
                if (itemIndex == count - 1)
                {
                    continue;
                }
                generator.Remove(childGeneratorPos, 1);
                RemoveInternalChildRange(i, 1);
            }
            return(desiredSize);
        }
Exemple #20
0
        void GenerateForwardFromBeginning()
        {
            //<SnippetGenerateForwardFromBeginningCODE>
            // Start generating items forward from the beginning of the item list
            GeneratorPosition       position  = new GeneratorPosition(-1, 0);
            GeneratorDirection      direction = GeneratorDirection.Forward;
            IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator;

            generator.StartAt(position, direction);
            //</SnippetGenerateForwardFromBeginningCODE>
        }
Exemple #21
0
        void GenerateBackFromEnd()
        {
            //<SnippetGenerateBackwardFromEndCODE>
            // Start generating items backward from the end of the item list
            GeneratorPosition       position  = new GeneratorPosition(-1, 0);
            GeneratorDirection      direction = GeneratorDirection.Backward;
            IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator;

            generator.StartAt(position, direction);
            //</SnippetGenerateBackwardFromEndCODE>
        }
Exemple #22
0
        /// <summary>
        /// Override for Measure.
        ///
        /// </summary>
        /// <param name="availableSize"/>
        /// <returns/>
        protected override Size MeasureOverride(Size availableSize)
        {
            this.halfSize           = new Size(availableSize.Width / 2.0, availableSize.Height);
            this.pageMaxDesiredSize = new Size();
            RadBook radBook = ItemsControl.GetItemsOwner((DependencyObject)this) as RadBook;

            if (radBook == null)
            {
                return(availableSize);
            }
            UIElementCollection children = this.Children;
            int count = radBook.Items.Count;
            IItemContainerGenerator containerGenerator = this.ItemContainerGenerator;

            if (radBook.IsVirtualizing)
            {
                int itemsCount = Math.Min(this.GenerateSpan, count - this.startingIndex);
                this.PrepareItems(containerGenerator, this.startingIndex, itemsCount);
                foreach (int itemIndex in (IEnumerable <int>) this.IndexCollection)
                {
                    using (containerGenerator.StartAt(containerGenerator.GeneratorPositionFromIndex(itemIndex), GeneratorDirection.Forward, true))
                    {
                        bool             isNewlyRealized;
                        FrameworkElement frameworkElement = containerGenerator.GenerateNext(out isNewlyRealized) as FrameworkElement;
                        if (frameworkElement != null)
                        {
                            if (isNewlyRealized)
                            {
                                this.AddInternalChild((UIElement)frameworkElement);
                                containerGenerator.PrepareItemContainer((DependencyObject)frameworkElement);
                            }
                            frameworkElement.Measure(this.halfSize);
                            this.pageMaxDesiredSize = new Size()
                            {
                                Height = Math.Max(this.pageMaxDesiredSize.Height, frameworkElement.DesiredSize.Height),
                                Width  = Math.Max(this.pageMaxDesiredSize.Width, frameworkElement.DesiredSize.Width)
                            };
                        }
                    }
                }
                this.CleanContainers();
            }
            else
            {
                this.PrepareItems(containerGenerator, 0, count);
            }
            double val1 = this.pageMaxDesiredSize.Width * 2.0;

            return(new Size()
            {
                Width = double.IsInfinity(availableSize.Width) ? val1 : Math.Min(val1, availableSize.Width),
                Height = double.IsInfinity(availableSize.Height) ? this.pageMaxDesiredSize.Height : Math.Min(this.pageMaxDesiredSize.Height, availableSize.Height)
            });
        }
        // I've isolated the layout specific code to this region. If you want to do something other than tiling, this is
        // where you'll make your changes

        /// <summary>
        /// Calculate the extent of the view based on the available size
        /// </summary>
        /// <param name="availableSize">available size</param>
        /// <param name="itemCount">number of data items</param>
        /// <returns></returns>
        private Size CalculateExtent(Size availableSize)
        {
            if (totalHeight > 0)
            {
                return(new Size(availableSize.Width, totalHeight));
            }
            // Die Gesamtgröße der Liste berechnen.
            ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);

            // We need to access InternalChildren before the generator to work around a bug
            UIElementCollection     children  = this.InternalChildren;
            IItemContainerGenerator generator = this.ItemContainerGenerator;

            // Get the generator position of the first visible data item
            GeneratorPosition startPos = generator.GeneratorPositionFromIndex(0);

            using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
            {
                for (int itemIndex = 0; itemIndex < itemsControl.Items.Count; ++itemIndex)
                {
                    itemsTopPosition.Add(totalHeight);

                    // Get or create the child
                    bool newlyRealized;
                    // UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;

                    // generator.PrepareItemContainer(child);

                    // Measurements will depend on layout algorithm
                    //child.Measure(GetChildSize());
                    AlbumViewItem avi = itemsControl.Items[itemIndex] as AlbumViewItem;
                    if (avi != null)
                    {
                        double height = Math.Max((avi.Tracks.Count * 18) + 10, 110);        // Minimale Höhe eines Albums
                        height       = Math.Min(height, 367);                               // Maximale Höhe eines Albums
                        totalHeight += height;
                        itemsHeight.Add(height);
                    }
                    AlbumViewTitle title = itemsControl.Items[itemIndex] as AlbumViewTitle;
                    if (title != null)
                    {
                        double height = 18;
                        totalHeight += height;
                        itemsHeight.Add(height);
                    }
                }
            }

            generator.RemoveAll();

            // See how big we are
            return(new Size(this.ActualWidth, totalHeight));
        }
Exemple #24
0
        protected override void OnInitialized(EventArgs e)
        {
            SizeChanged += OnSizeChanged;

            base.OnInitialized(e);

            _itemsControl = ItemsControl.GetItemsOwner(this);
            //TODO: Why not just use InternalChildren everywhere?
            _children = InternalChildren;
            //TODO: Why not just use ItemContainerGenerator everywhere?
            _generator = ItemContainerGenerator;
        }
        private void DumpGeneratorContent()
        {
            IItemContainerGenerator generator    = ItemContainerGenerator;
            ItemsControl            itemsControl = ItemsControl.GetItemsOwner(this);

            Debug.WriteLine("Generator positions");
            for (int i = 0; i < itemsControl.Items.Count; i++)
            {
                GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
                Debug.WriteLine("Item index: {0}, Gen pos: Index: {1} Offset: {2}", i, pos.Index, pos.Offset);
            }
        }
Exemple #26
0
        static TreeViewItem SelectTreeViewItemForBinding(object dataItem, ItemsControl ic)
        {
            if (ic == null || dataItem == null || !ic.HasItems)
            {
                return(null);
            }
            IItemContainerGenerator generator = ic.ItemContainerGenerator;

            if (ic.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                foreach (var t in ic.Items)
                {
                    var tvi = ic.ItemContainerGenerator.ContainerFromItem(t);
                    if (t == dataItem)
                    {
                        return(tvi as TreeViewItem);
                    }

                    var tmp = SelectTreeViewItemForBinding(dataItem, tvi as ItemsControl);
                    if (tmp != null)
                    {
                        return(tmp);
                    }
                }
            }
            else
            {
                using (generator.StartAt(generator.GeneratorPositionFromIndex(-1), GeneratorDirection.Forward))
                {
                    foreach (var t in ic.Items)
                    {
                        bool isNewlyRealized;
                        var  tvi = generator.GenerateNext(out isNewlyRealized);
                        if (isNewlyRealized)
                        {
                            generator.PrepareItemContainer(tvi);
                        }
                        if (t == dataItem)
                        {
                            return(tvi as TreeViewItem);
                        }

                        var tmp = SelectTreeViewItemForBinding(dataItem, tvi as ItemsControl);
                        if (tmp != null)
                        {
                            return(tmp);
                        }
                    }
                }
            }
            return(null);
        }
Exemple #27
0
        /// <summary>
        /// Measure the children
        /// </summary>
        /// <param name="availableSize">Size available</param>
        /// <returns>Size desired</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            UpdateScrollInfo(availableSize);
            EnsureRealizedChildren();
            Size desiredSize = new Size(availableSize.Width, availableSize.Height);

            iChildrenPerRow = (int)Math.Floor(availableSize.Width / ItemSize);

            // Figure out range that's visible based on layout algorithm
            int firstVisibleItemIndex, lastVisibleItemIndex;

            GetVisibleRange(out firstVisibleItemIndex, out lastVisibleItemIndex);

            if (iPreviousFirstVisibleItemIndex == -1 || iPreviousFirstVisibleItemIndex != firstVisibleItemIndex || iPreviousLastVisibleItemIndex != lastVisibleItemIndex || availableSize.Width != iPreviousAvailableSize.Width || availableSize.Height != iPreviousAvailableSize.Height)
            {
                iPreviousAvailableSize         = availableSize;
                iPreviousFirstVisibleItemIndex = firstVisibleItemIndex;
                iPreviousLastVisibleItemIndex  = lastVisibleItemIndex;
                IList        children   = this.RealizedChildren;
                ItemsControl itemsOwner = ItemsControl.GetItemsOwner(this);
                int          itemCount  = (itemsOwner != null) ? itemsOwner.Items.Count : 0;


                IItemContainerGenerator generator = this.ItemContainerGenerator;
                CleanupContainers(firstVisibleItemIndex, itemsOwner);

                GeneratorPosition position = this.IndexToGeneratorPositionForStart(firstVisibleItemIndex, out this.iFirstVisibleChildIndex);
                int childIndex             = this.iFirstVisibleChildIndex;
                if (itemCount > 0)
                {
                    double actualSize = availableSize.Width / iChildrenPerRow;
                    Size   size       = new Size(actualSize, actualSize);
                    using (generator.StartAt(position, GeneratorDirection.Forward, true))
                    {
                        for (int i = firstVisibleItemIndex; i <= lastVisibleItemIndex; i++)
                        {
                            bool      newlyRealized;
                            UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;
                            if (child == null)
                            {
                                break;
                            }
                            this.AddContainerFromGenerator(childIndex, child, newlyRealized);
                            childIndex++;
                            child.Measure(size);
                        }
                    }
                }
            }
            this.DisconnectRecycledContainers();
            return(desiredSize);
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            IItemContainerGenerator itemContainerGenerator = base.ItemContainerGenerator;

            this.UpdateScrollInfo(finalSize);
            for (int i = 0; i < base.Children.Count; i++)
            {
                UIElement child     = base.Children[i];
                int       itemIndex = itemContainerGenerator.IndexFromGeneratorPosition(new GeneratorPosition(i, 0));
                this.ArrangeChild(itemIndex, child, finalSize);
            }
            return(finalSize);
        }
        private void RealizeFirstItem()
        {
            IItemContainerGenerator generator = ItemContainerGenerator;
            GeneratorPosition       pos       = generator.GeneratorPositionFromIndex(0);

            using (generator.StartAt(pos, GeneratorDirection.Forward))
            {
                var element = generator.GenerateNext() as UIElement;

                generator.PrepareItemContainer(element);

                AddInternalChild(element);
            }
        }
Exemple #30
0
        void GenerateForwardFromMiddle()
        {
            //<SnippetGenerateForwardFromMiddleCODE>
            // Start generating items forward,
            // starting with the first unrealized item (offset of 1),
            // after the 5th realized item
            // (the item with index 4 among all realized items) in the list
            GeneratorPosition       position  = new GeneratorPosition(4, 1);
            GeneratorDirection      direction = GeneratorDirection.Forward;
            IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator;

            generator.StartAt(position, direction);
            //</SnippetGenerateForwardFromMiddleCODE>
        }
        private IList<ItemContainerInfo> Materialize(
            IItemContainerGenerator generator,
            int index,
            string[] items)
        {
            var result = new List<ItemContainerInfo>();

            foreach (var item in items)
            {
                var container = generator.Materialize(index++, item, null);
                result.Add(container);
            }

            return result;
        }
Exemple #32
0
        /// <summary>
        ///     Helper method to build generator position out to index
        /// </summary>
        private static GeneratorPosition IndexToGeneratorPositionForStart(IItemContainerGenerator generator, int index, out int childIndex)
        {
            GeneratorPosition position = (generator != null) ? generator.GeneratorPositionFromIndex(index) : new GeneratorPosition(-1, index + 1);

            // Determine the position in the children collection for the first
            // generated container.  This assumes that generator.StartAt will be called
            // with direction=Forward and allowStartAtRealizedItem=true.
            childIndex = (position.Offset == 0) ? position.Index : position.Index + 1;

            return position;
        }
Exemple #33
0
        /// <summary>
        ///     Method which virtualizes the children which are determined to be unused. 
        ///     Eligible candidates for virtualization are those which are not in block list.
        ///     Some exceptions to the criterion are the cells which are in edit mode, or
        ///     if item is its own container.
        /// </summary>
        private void VirtualizeChildren(List<RealizedColumnsBlock> blockList, IItemContainerGenerator generator)
        {
            ObservableCollection<DataGridColumn> columns = ParentDataGrid.Columns;
            int columnCount = columns.Count;
            int columnIterator = 0;
            IList children = RealizedChildren;
            int childrenCount = children.Count;
            if (childrenCount == 0)
            {
                return;
            }

            int blockIndex = 0;
            int blockCount = blockList.Count;
            RealizedColumnsBlock block = (blockCount > 0 ? blockList[blockIndex] : new RealizedColumnsBlock(-1, -1, -1));
            bool pastLastBlock = (blockCount > 0 ? false : true);

            int cleanupRangeStart = -1;
            int cleanupCount = 0;
            int lastVirtualizedColumnIndex = -1;

            ItemsControl parentPresenter = ParentPresenter;
            DataGridCellsPresenter cellsPresenter = parentPresenter as DataGridCellsPresenter;
            DataGridColumnHeadersPresenter headersPresenter = parentPresenter as DataGridColumnHeadersPresenter;

            for (int i = 0; i < childrenCount; i++)
            {
                int columnIndex = i;
                UIElement child = children[i] as UIElement;
                IProvideDataGridColumn columnProvider = child as IProvideDataGridColumn;
                if (columnProvider != null)
                {
                    DataGridColumn column = columnProvider.Column;
                    for (; columnIterator < columnCount; columnIterator++)
                    {
                        if (column == columns[columnIterator])
                        {
                            break;
                        }
                    }

                    columnIndex = columnIterator++;
                    Debug.Assert(columnIndex < columnCount, "columnIndex should be less than column count");
                }

                bool virtualizeChild = pastLastBlock || !InBlockOrNextBlock(blockList, columnIndex, ref blockIndex, ref block, out pastLastBlock);

                DataGridCell cell = child as DataGridCell;
                if ((cell != null && (cell.IsEditing || cell.IsKeyboardFocusWithin)) ||
                    (cellsPresenter != null &&
                    cellsPresenter.IsItemItsOwnContainerInternal(cellsPresenter.Items[columnIndex])) ||
                    (headersPresenter != null &&
                    headersPresenter.IsItemItsOwnContainerInternal(headersPresenter.Items[columnIndex])))
                {
                    virtualizeChild = false;
                }

                if (!columns[columnIndex].IsVisible)
                {
                    virtualizeChild = true;
                }

                if (virtualizeChild)
                {
                    if (cleanupRangeStart == -1)
                    {
                        cleanupRangeStart = i;
                        cleanupCount = 1;
                    }
                    else if (lastVirtualizedColumnIndex == columnIndex - 1)
                    {
                        cleanupCount++;
                    }
                    else
                    {
                        // Meaning that two consecutive children to be virtualized are not corresponding to
                        // two consecutive columns
                        CleanupRange(children, generator, cleanupRangeStart, cleanupCount);
                        childrenCount -= cleanupCount;
                        i -= cleanupCount;
                        cleanupCount = 1;
                        cleanupRangeStart = i;
                    }

                    lastVirtualizedColumnIndex = columnIndex;
                }
                else
                {
                    if (cleanupCount > 0)
                    {
                        CleanupRange(children, generator, cleanupRangeStart, cleanupCount);
                        childrenCount -= cleanupCount;
                        i -= cleanupCount;
                        cleanupCount = 0;
                        cleanupRangeStart = -1;
                    }
                }
            }

            if (cleanupCount > 0)
            {
                CleanupRange(children, generator, cleanupRangeStart, cleanupCount);
            }
        }
Exemple #34
0
        /// <summary>
        ///     Method which cleans up a given range of children
        /// </summary>
        private void CleanupRange(IList children, IItemContainerGenerator generator, int startIndex, int count)
        {
            if (count <= 0)
            {
                return;
            }

            if (IsVirtualizing && InRecyclingMode)
            {
                Debug.Assert(startIndex >= 0);
                Debug.Assert(children == _realizedChildren, "the given child list must be the _realizedChildren list when recycling");

                // Recycle and remove the children from realized list
                GeneratorPosition position = new GeneratorPosition(startIndex, 0);
                ((IRecyclingItemContainerGenerator)generator).Recycle(position, count);
                _realizedChildren.RemoveRange(startIndex, count);
            }
            else
            {
                // Remove the desired range of children
                RemoveInternalChildRange(startIndex, count);
                generator.Remove(new GeneratorPosition(startIndex, 0), count);
            }
        }
Exemple #35
0
 protected override void OnInitialized(EventArgs e)
 {
     _itemsControl = ItemsControl.GetItemsOwner(this);
     _children = InternalChildren;
     _generator = ItemContainerGenerator;
     this.SizeChanged += new SizeChangedEventHandler(this.Resizing);
     base.OnInitialized(e);
 }
Exemple #36
0
        private void Realize(UIElementCollection children, IItemContainerGenerator generator)
        {
            /*********************** 代码块解释 *********************************
             *
             * 虚拟化模式下,为了保证编辑状态的焦点不会丢失,生成单元格过程中不再移除已经之前生成好的单元格。
             * 所有已经生成好的单元格都会被 generator 存储起来,
             * 而以下过程只是修改 InternalChildren,即可视树中的元素:
             * 一开始,先把所有可视树子节点移除,然后不论是否刚生成的单元格,都直接加入到可视树中。
             *
            **********************************************************************/

            foreach (var child in children)
            {
                var cell = child as TreeGridCell;
                if (cell == null) break;

                cell.VisibleOnVirtualizing = false;
            }

            this.RemoveInternalChildRange(0, children.Count);

            // 获取第一个可视元素位置信息
            var start = generator.GeneratorPositionFromIndex(this._from);
            using (generator.StartAt(start, GeneratorDirection.Forward, true))
            {
                for (int i = this._from; i <= this._to; i++)
                {
                    bool isNewlyRealized;
                    var container = generator.GenerateNext(out isNewlyRealized) as UIElement;

                    this.AddInternalChild(container);

                    var cell = container as TreeGridCell;
                    if (cell != null) cell.VisibleOnVirtualizing = true;

                    if (isNewlyRealized)
                    {
                        generator.PrepareItemContainer(container);
                    }
                    else
                    {
                        //正在编辑的有焦点的控件,需要还原其焦点。
                        if (cell != null)
                        {
                            this._cellsPresenter.RestoreEditingCellFocus(cell);
                        }
                    }
                }
            }
        }
            public ChildGenerator(VirtualizingWrapPanel owner)
            {
                this.owner = owner;

                var childrenCount = owner.InternalChildren.Count;
                this.generator = owner.ItemContainerGenerator;
            }
        private void ManageCleanup( 
            UIElementCollection children, 
            ItemsControl itemsControl,
            IItemContainerGenerator generator, 
            int childIndex,
            int minDesiredGenerated,
            int maxDesiredGenerated,
            ref int counter, 
            ref int cleanupRangeStart,
            ref int cleanupCount, 
            ref int lastGeneratedIndex, 
            out int counterAdjust)
        { 
            counterAdjust = 0;
            bool performCleanup = false;
            bool countThisChild = false;
            int generatedIndex = GetGeneratedIndex(childIndex); 

            if (OutsideMinMax(generatedIndex, minDesiredGenerated, maxDesiredGenerated) && 
                NotifyCleanupItem(childIndex, children, itemsControl)) 
            {
                // The item can be re-virtualized. 
                if ((generatedIndex - lastGeneratedIndex) == 1)
                {
                    // Add another to the current batch.
                    cleanupCount++; 
                }
                else 
                { 
                    // There was a gap in generated items. Cleanup any from the previous batch.
                    performCleanup = countThisChild = true; 
                }
            }
            else
            { 
                // The item cannot be re-virtualized. Cleanup any from the previous batch.
                performCleanup = true; 
            } 

            if (performCleanup) 
            {
                // Cleanup a batch of items
                if (cleanupCount > 0)
                { 
                    CleanupRange(children, generator, cleanupRangeStart, cleanupCount);
                    counterAdjust = cleanupCount; 
                    counter -= counterAdjust; 
                    childIndex -= counterAdjust;
                    cleanupCount = 0; 
                }

                if (countThisChild)
                { 
                    // The current child was not included in the batch and should be saved for later
                    cleanupRangeStart = childIndex; 
                    cleanupCount = 1; 
                }
                else 
                {
                    // The next child will start the next batch.
                    cleanupRangeStart = childIndex + 1;
                } 
            }
            lastGeneratedIndex = generatedIndex; 
        } 
        private void MeasureChild(
            ref IItemContainerGenerator generator,
            ref IContainItemStorage itemStorageProvider,
            ref object parentItem,
            ref bool hasUniformOrAverageContainerSizeBeenSet,
            ref double computedUniformOrAverageContainerSize,
            ref bool computedAreContainersUniformlySized,
            ref IList items,
            ref object item,
            ref IList children,
            ref int childIndex,
            ref bool visualOrderChanged,
            ref bool isHorizontal,
            ref Size childConstraint,
            ref Rect viewport,
            ref VirtualizationCacheLength cacheSize,
            ref VirtualizationCacheLengthUnit cacheUnit,
            ref bool foundFirstItemInViewport,
            ref double firstItemInViewportOffset,
            ref Size stackPixelSize,
            ref Size stackPixelSizeInViewport,
            ref Size stackPixelSizeInCacheBeforeViewport,
            ref Size stackPixelSizeInCacheAfterViewport,
            ref Size stackLogicalSize,
            ref Size stackLogicalSizeInViewport,
            ref Size stackLogicalSizeInCacheBeforeViewport,
            ref Size stackLogicalSizeInCacheAfterViewport,
            ref bool mustDisableVirtualization,
            bool isBeforeFirstItem,
            bool isAfterFirstItem,
            bool isAfterLastItem,
            bool skipActualMeasure,
            bool skipGeneration,
            ref bool hasBringIntoViewContainerBeenMeasured,
            ref bool hasVirtualizingChildren)
        {
            UIElement child = null;
            IHierarchicalVirtualizationAndScrollInfo virtualizingChild = null;
            Rect childViewport = Rect.Empty;
            VirtualizationCacheLength childCacheSize = new VirtualizationCacheLength(0.0);
            VirtualizationCacheLengthUnit childCacheUnit = VirtualizationCacheLengthUnit.Pixel;
            Size childDesiredSize = new Size();

            //
            // Get and connect the next child.
            //
            if (!skipActualMeasure && !skipGeneration)
            {
                bool newlyRealized;
                child = generator.GenerateNext(out newlyRealized) as UIElement;

                ItemContainerGenerator icg;
                if (child == null && (icg = generator as ItemContainerGenerator) != null)
                {
                    icg.Verify();
                }

                visualOrderChanged |= AddContainerFromGenerator(childIndex, child, newlyRealized, isBeforeFirstItem);
            }
            else
            {
                child = (UIElement)children[childIndex];
            }

            hasBringIntoViewContainerBeenMeasured |= (child == _bringIntoViewContainer);

            //
            // Set viewport constraints
            //

            bool isChildHorizontal = isHorizontal;
            virtualizingChild = GetVirtualizingChild(child, ref isChildHorizontal);

            SetViewportForChild(
                isHorizontal,
                itemStorageProvider,
                computedAreContainersUniformlySized,
                computedUniformOrAverageContainerSize,
                mustDisableVirtualization,
                child,
                virtualizingChild,
                item,
                isBeforeFirstItem,
                isAfterFirstItem,
                firstItemInViewportOffset,
                viewport,
                cacheSize,
                cacheUnit,
                stackPixelSize,
                stackPixelSizeInViewport,
                stackPixelSizeInCacheBeforeViewport,
                stackPixelSizeInCacheAfterViewport,
                stackLogicalSize,
                stackLogicalSizeInViewport,
                stackLogicalSizeInCacheBeforeViewport,
                stackLogicalSizeInCacheAfterViewport,
                out childViewport,
                ref childCacheSize,
                ref childCacheUnit);

            //
            // Measure the child
            //

            if (!skipActualMeasure)
            {
                child.Measure(childConstraint);
            }

            childDesiredSize = child.DesiredSize;

            //
            // Accumulate child size.
            //

            if (virtualizingChild != null)
            {
                //
                // Update the virtualizingChild once more to really be sure
                // that we can trust the Desired values from it. Previously
                // we may have bypassed some checks because the ItemsHost
                // wasn't connected.
                //
                virtualizingChild = GetVirtualizingChild(child, ref isChildHorizontal);

                mustDisableVirtualization |=
                    (virtualizingChild != null && virtualizingChild.MustDisableVirtualization) ||
                    isChildHorizontal != isHorizontal;
            }

            Size childPixelSize, childPixelSizeInViewport, childPixelSizeInCacheBeforeViewport, childPixelSizeInCacheAfterViewport;
            Size childLogicalSize, childLogicalSizeInViewport, childLogicalSizeInCacheBeforeViewport, childLogicalSizeInCacheAfterViewport;

            GetSizesForChild(
                isHorizontal,
                isChildHorizontal,
                isBeforeFirstItem,
                isAfterLastItem,
                virtualizingChild,
                childDesiredSize,
                childViewport,
                childCacheSize,
                childCacheUnit,
                out childPixelSize,
                out childPixelSizeInViewport,
                out childPixelSizeInCacheBeforeViewport,
                out childPixelSizeInCacheAfterViewport,
                out childLogicalSize,
                out childLogicalSizeInViewport,
                out childLogicalSizeInCacheBeforeViewport,
                out childLogicalSizeInCacheAfterViewport);

            UpdateStackSizes(
                isHorizontal,
                foundFirstItemInViewport,
                childPixelSize,
                childPixelSizeInViewport,
                childPixelSizeInCacheBeforeViewport,
                childPixelSizeInCacheAfterViewport,
                childLogicalSize,
                childLogicalSizeInViewport,
                childLogicalSizeInCacheBeforeViewport,
                childLogicalSizeInCacheAfterViewport,
                ref stackPixelSize,
                ref stackPixelSizeInViewport,
                ref stackPixelSizeInCacheBeforeViewport,
                ref stackPixelSizeInCacheAfterViewport,
                ref stackLogicalSize,
                ref stackLogicalSizeInViewport,
                ref stackLogicalSizeInCacheBeforeViewport,
                ref stackLogicalSizeInCacheAfterViewport);

            //
            // Cache the container size.
            //

            if (VirtualizingPanel.GetShouldCacheContainerSize(child))
            {
                SetContainerSizeForItem(
                    itemStorageProvider,
                    parentItem,
                    item,
                    IsPixelBased ? childPixelSize : childLogicalSize,
                    isHorizontal,
                    ref hasUniformOrAverageContainerSizeBeenSet,
                    ref computedUniformOrAverageContainerSize,
                    ref computedAreContainersUniformlySized);
            }

            if (virtualizingChild != null)
            {
                hasVirtualizingChildren = true;
            }
        }
Exemple #40
0
        /// <summary>
        /// 清除不显示的单元格。
        /// </summary>
        /// <param name="children"></param>
        /// <param name="generator"></param>
        private void Cleanup(UIElementCollection children, IItemContainerGenerator generator)
        {
            //清除不需要显示的子元素,注意从集合后向前操作,以免造成操作过程中元素索引发生改变
            for (int i = children.Count - 1; i > -1; i--)
            {
                // 通过已显示的子元素的位置信息得出元素索引
                var childGeneratorPos = new GeneratorPosition(i, 0);
                int itemIndex = generator.IndexFromGeneratorPosition(childGeneratorPos);

                // 移除不再显示的元素
                if (itemIndex < this._from || itemIndex > this._to)
                {
                    generator.Remove(childGeneratorPos, 1);
                    this.RemoveInternalChildRange(i, 1);
                }
            }
        }
Exemple #41
0
        /// <summary>
        ///     Helper method which generates and measures children of 
        ///     a given block of indices
        /// </summary>
        private Size GenerateChildren(
            IItemContainerGenerator generator,
            int startIndex,
            int endIndex,
            Size constraint)
        {
            double measureWidth = 0.0;
            double measureHeight = 0.0;
            int childIndex;
            GeneratorPosition startPos = IndexToGeneratorPositionForStart(generator, startIndex, out childIndex);
            DataGrid parentDataGrid = ParentDataGrid;
            using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
            {
                Size childSize;
                for (int i = startIndex; i <= endIndex; i++)
                {
                    if (!parentDataGrid.Columns[i].IsVisible)
                    {
                        continue;
                    }

                    if (null == GenerateChild(generator, constraint, parentDataGrid.Columns[i], ref childIndex, out childSize))
                    {
                        return new Size(measureWidth, measureHeight);
                    }

                    measureWidth += childSize.Width;
                    measureHeight = Math.Max(measureHeight, childSize.Height);
                }
            }

            return new Size(measureWidth, measureHeight);
        }
Exemple #42
0
        /// <summary>
        ///     Helper method which generates and measures a
        ///     child of given index
        /// </summary>
        private UIElement GenerateChild(
            IItemContainerGenerator generator,
            Size constraint,
            DataGridColumn column,
            ref IDisposable generatorState,
            ref int childIndex,
            out Size childSize)
        {
            if (generatorState == null)
            {
                generatorState = generator.StartAt(IndexToGeneratorPositionForStart(generator, childIndex, out childIndex), GeneratorDirection.Forward, true);
            }

            return GenerateChild(generator, constraint, column, ref childIndex, out childSize);
        }
        private void MeasureExistingChildBeyondExtendedViewport(
            ref IItemContainerGenerator generator,
            ref IContainItemStorage itemStorageProvider,
            ref object parentItem,
            ref bool hasUniformOrAverageContainerSizeBeenSet,
            ref double computedUniformOrAverageContainerSize,
            ref bool computedAreContainersUniformlySized,
            ref IList items,
            ref IList children,
            ref int childIndex,
            ref bool visualOrderChanged,
            ref bool isHorizontal,
            ref Size childConstraint,
            ref bool foundFirstItemInViewport,
            ref double firstItemInViewportOffset,
            ref bool mustDisableVirtualization,
            ref bool hasVirtualizingChildren,
            ref bool hasBringIntoViewContainerBeenMeasured)
        {
            object item = ((ItemContainerGenerator)generator).ItemFromContainer((UIElement)children[childIndex]);
            Rect viewport = new Rect();
            VirtualizationCacheLength cacheSize = new VirtualizationCacheLength();
            VirtualizationCacheLengthUnit cacheUnit = VirtualizationCacheLengthUnit.Pixel;
            Size stackPixelSize = new Size();
            Size stackPixelSizeInViewport = new Size();
            Size stackPixelSizeInCacheBeforeViewport = new Size();
            Size stackPixelSizeInCacheAfterViewport = new Size();
            Size stackLogicalSize = new Size();
            Size stackLogicalSizeInViewport = new Size();
            Size stackLogicalSizeInCacheBeforeViewport = new Size();
            Size stackLogicalSizeInCacheAfterViewport = new Size();
            bool isBeforeFirstItem = childIndex < _firstItemInExtendedViewportChildIndex;
            bool isAfterFirstItem = childIndex > _firstItemInExtendedViewportChildIndex;
            bool isAfterLastItem = childIndex > _firstItemInExtendedViewportChildIndex + _actualItemsInExtendedViewportCount;
            bool skipActualMeasure = false;
            bool skipGeneration = true;

            MeasureChild(
                ref generator,
                ref itemStorageProvider,
                ref parentItem,
                ref hasUniformOrAverageContainerSizeBeenSet,
                ref computedUniformOrAverageContainerSize,
                ref computedAreContainersUniformlySized,
                ref items,
                ref item,
                ref children,
                ref childIndex,
                ref visualOrderChanged,
                ref isHorizontal,
                ref childConstraint,
                ref viewport,
                ref cacheSize,
                ref cacheUnit,
                ref foundFirstItemInViewport,
                ref firstItemInViewportOffset,
                ref stackPixelSize,
                ref stackPixelSizeInViewport,
                ref stackPixelSizeInCacheBeforeViewport,
                ref stackPixelSizeInCacheAfterViewport,
                ref stackLogicalSize,
                ref stackLogicalSizeInViewport,
                ref stackLogicalSizeInCacheBeforeViewport,
                ref stackLogicalSizeInCacheAfterViewport,
                ref mustDisableVirtualization,
                isBeforeFirstItem,
                isAfterFirstItem,
                isAfterLastItem,
                skipActualMeasure,
                skipGeneration,
                ref hasBringIntoViewContainerBeenMeasured,
                ref hasVirtualizingChildren);
        }
        private void RealizeElements(List<int> dataIndexesToKeep, IItemContainerGenerator generator)
        {
            foreach (var dataIndex in dataIndexesToKeep)
            {
                var position = generator.GeneratorPositionFromIndex(dataIndex);
                using (generator.StartAt(position, GeneratorDirection.Forward, true))
                {
                    // GeneratorPosition's documentation is a bit cryptic:
                    // - Index gets the index of the control corresponding to this data item, or the next-lowest data
                    //	item that is realized (i.e. has a control).
                    // - Offset gets the number of data items between this item and the previous data item that is realized.
                    //
                    // So if Offset is 0, this item is *not* virtualized.
                    int controlIndexToInsert = (position.Offset == 0) ? position.Index : position.Index + 1;

                    bool newlyRealized;
                    UIElement control = generator.GenerateNext(out newlyRealized) as UIElement;

                    if (newlyRealized)
                    {
                        if (controlIndexToInsert >= this.InternalChildren.Count)
                        {
                            base.AddInternalChild(control);
                        }
                        else
                        {
                            base.InsertInternalChild(controlIndexToInsert, control);
                        }
                        generator.PrepareItemContainer(control);
                    }
                }
            }
        }
Exemple #45
0
 private static bool IsItemsHostPanel(IItemContainerGenerator generator, DependencyObject target)
 {
     var panel = target as Panel;
     return panel != null && panel.IsItemsHost && generator == generator.GetItemContainerGeneratorForPanel(panel);
 }
Exemple #46
0
        /// <summary>
        ///     Helper method which generates and measures a
        ///     child of given index
        /// </summary>
        private UIElement GenerateChild(
            IItemContainerGenerator generator,
            Size constraint,
            DataGridColumn column,
            ref int childIndex,
            out Size childSize)
        {
            bool newlyRealized;
            UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;
            if (child == null)
            {
                childSize = new Size();
                return null;
            }

            AddContainerFromGenerator(childIndex, child, newlyRealized);
            childIndex++;

            MeasureChild(child, constraint);

            DataGridLength width = column.Width;
            childSize = child.DesiredSize;
            if (!DoubleUtil.IsNaN(width.DisplayValue))
            {
                childSize = new Size(width.DisplayValue, childSize.Height);
            }

            return child;
        }
Exemple #47
0
        protected override Size MeasureOverride(Size availableSize)
        {
            // Make sure _realizedChildren exists and contains all children
            EnsureRealizedChildren();

            // Get the ItemContainerGenerator that generates UI items for this panel
            _generator = ItemContainerGenerator;

            // Get the panel
            TwitterPanel host = ItemsControl.GetItemsOwner(this) as TwitterPanel;

            // Keep track of all data items, assigning X,Y,Z coords to them
            UpdateItemsTracker(host);

            // Work out how many items we want to show. We show 21 - the previous item
            // from the selected item (so it doesn't suddenly disappear when we
            // scroll past it) and 20 more. More than that and we can't really see them
            _startPosition = 0;
            if (host.SelectedIndex >= 0)
            {
                _startPosition = host.SelectedIndex - 1;
                if (_startPosition < 0)
                {
                    _startPosition = 0;
                }
            }
            _endPosition = Math.Min(host.Items.Count - 1, _startPosition + 20);
            if (_endPosition < 0)
            {
                _endPosition = 0;
            }

            // Recycle any existing containers we don't need any more so the
            // ItemsContainerGenerator can reuse them instead of creating more
            RecycleContainers();
            if (_startPosition >= _endPosition && _endPosition > 0) return _previousMeasureSize;
            GeneratorPosition start = _generator.GeneratorPositionFromIndex(_startPosition);
            int childIndex = (start.Offset == 0) ? start.Index : start.Index + 1;

            using (_generator.StartAt(start, GeneratorDirection.Forward, true))
            {
                for (int i = _startPosition; i <= _endPosition; ++i)
                {
                    bool isNewlyRealized;

                    UIElement child = _generator.GenerateNext(out isNewlyRealized) as UIElement;
                    if (child == null) continue;

                    if (isNewlyRealized)
                    {
                        InsertContainer(childIndex, child, false);
                    }
                    else
                    {
                        if (childIndex >= _realizedChildren.Count || !(_realizedChildren[childIndex] == child))
                        {
                            // we have a recycled container (if it was realized container it would have been returned in the
                            // propert location). Note also that recycled containers are NOT in the _realizedChildren list.
                            InsertContainer(childIndex, child, true);
                        }
                        else
                        {
                            // previously realized child, so do nothing
                        }
                    }
                    childIndex++;

                    if (isNewlyRealized)
                    {
                        PlaneProjection proj = (PlaneProjection)child.Projection;
                        ItemTracker tracked = trackedItems[i];
                        proj.GlobalOffsetX = tracked.X;
                        proj.GlobalOffsetY = tracked.Y;
                        proj.GlobalOffsetZ = tracked.Z;
                    }

                    #region Measure Logic
                    child.Measure(availableSize);

                    #endregion Measure Logic
                }
            }

            DisconnectRecycledContainers();
            var oldrealized = realizedTrackers;
            if (oldrealized == null)
            {
                oldrealized = new List<ItemTracker>();
            }
            realizedTrackers = (from item in _realizedChildren.Cast<FrameworkElement>()
                                join track in trackedItems on item.DataContext equals track.Item
                                select track).ToList();

            var discarded = (from item in oldrealized
                            join j in realizedTrackers on item equals j into joined
                            from j in joined.DefaultIfEmpty()
                            where j == null
                            select item).ToList();
            var added = (from item in realizedTrackers
                         join j in oldrealized on item equals j into joined
                         from j in joined.DefaultIfEmpty()
                         where j == null
                         select item).ToList();

            var real = from child in _realizedChildren.Cast<FrameworkElement>()
                       join j in realizedTrackers on child.DataContext equals j.Item
                       select new { Track = j, Element = child };
            foreach (var add in real)
            {
                PlaneProjection proj = add.Element.Projection as PlaneProjection;
                proj.GlobalOffsetX = add.Track.X - ViewX;
                proj.GlobalOffsetY = add.Track.Y - ViewY;
                proj.GlobalOffsetZ = add.Track.Z - ViewZ;
            }

            if (double.IsPositiveInfinity(availableSize.Width) || double.IsPositiveInfinity(availableSize.Height))
            {
                _previousMeasureSize = new Size(1000000, 1000000);
            }
            else
            {
                _previousMeasureSize = availableSize;
            }
            return _previousMeasureSize;
        }
Exemple #48
0
 /// <summary>
 ///     Method which ensures that atleast one column
 ///     header is generated. Such a generation would
 ///     help in determination of the height.
 /// </summary>
 private Size EnsureAtleastOneHeader(IItemContainerGenerator generator,
     Size constraint,
     List<int> realizedColumnIndices,
     List<int> realizedColumnDisplayIndices)
 {
     DataGrid parentDataGrid = ParentDataGrid;
     int columnCount = parentDataGrid.Columns.Count;
     Size childSize = new Size();
     if (RealizedChildren.Count == 0 && columnCount > 0)
     {
         for (int i = 0; i < columnCount; i++)
         {
             DataGridColumn column = parentDataGrid.Columns[i];
             if (column.IsVisible)
             {
                 int childIndex = i;
                 using (generator.StartAt(IndexToGeneratorPositionForStart(generator, childIndex, out childIndex), GeneratorDirection.Forward, true))
                 {
                     UIElement child = GenerateChild(generator, constraint, column, ref childIndex, out childSize);
                     if (child != null)
                     {
                         int displayIndexListIterator = 0;
                         AddToIndicesListIfNeeded(
                             realizedColumnIndices,
                             realizedColumnDisplayIndices,
                             i,
                             column.DisplayIndex,
                             ref displayIndexListIterator);
                         return childSize;
                     }
                 }
             }
         }
     }
     return childSize;
 }
Exemple #49
0
 private void OnIsItemsHostChanged(DependencyPropertyChangedEventArgs e)
 {
     ItemContainerGenerator = IsItemsHost && TemplatedParent is ItemsControl ? ((ItemsControl)TemplatedParent).ItemContainerGenerator : null;
 }
        /// <summary>
        /// handles the ItemContainerGeneratorProperty changes.
        /// </summary>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        private void OnItemContainerGeneratorChanged(IItemContainerGenerator oldValue, IItemContainerGenerator newValue)
        {

        }
Exemple #51
0
        private void CleanupRange(IList children, IItemContainerGenerator generator, int startIndex, int count)
        {
            if (InRecyclingMode)
            {
                Debug.Assert(startIndex >= 0 && count > 0);
                Debug.Assert(children == _realizedChildren, "the given child list must be the _realizedChildren list when recycling");

                if (ScrollTracer.IsEnabled && ScrollTracer.IsTracing(this))
                {
                    List<String> list = new List<String>(count);
                    for (int i=0; i<count; ++i)
                    {
                        list.Add(ContainerPath((DependencyObject)children[startIndex + i]));
                    }

                    ScrollTracer.Trace(this, ScrollTraceOp.RecycleChildren,
                        startIndex, count, list);
                }

                ((IRecyclingItemContainerGenerator)generator).Recycle(new GeneratorPosition(startIndex, 0), count);

                // The call to Recycle has caused the ItemContainerGenerator to remove some items
                // from its list of realized items; we adjust _realizedChildren to match.
                _realizedChildren.RemoveRange(startIndex, count);
            }
            else
            {
                if (ScrollTracer.IsEnabled && ScrollTracer.IsTracing(this))
                {
                    List<String> list = new List<String>(count);
                    for (int i=0; i<count; ++i)
                    {
                        list.Add(ContainerPath((DependencyObject)children[startIndex + i]));
                    }

                    ScrollTracer.Trace(this, ScrollTraceOp.RemoveChildren,
                        startIndex, count, list);
                }

                // Remove the desired range of children
                VirtualizingPanel.RemoveInternalChildRange((UIElementCollection)children, startIndex, count);
                generator.Remove(new GeneratorPosition(startIndex, 0), count);

                // We only need to adjust the childIndex if the visual tree
                // is changing and this is the only case that that happens
                AdjustFirstVisibleChildIndex(startIndex, count);
            }
        }
        private void ReVirtualizeElements(List<int> dataIndexesToRealize, IItemContainerGenerator generator)
        {
            var controlIndexes = this.InternalChildren.Cast<UIElement>().Select(
                (element, i) => new
                {
                    ControlIndex = i,
                    DataIndex = generator.IndexFromGeneratorPosition(new GeneratorPosition(i, 0)),
                })
                .ToList();

            foreach (var itemToRemove in controlIndexes
                .Where(idx => !dataIndexesToRealize.Contains(idx.DataIndex))
                .OrderByDescending(idx => idx.ControlIndex))
            {
                generator.Remove(position: new GeneratorPosition(itemToRemove.ControlIndex, 0), count: 1);
                base.RemoveInternalChildRange(itemToRemove.ControlIndex, 1);
            }
        }
Exemple #53
0
        //以下代码只有解决焦点的恢复问题后才可继续使用。
        /// <summary>
        /// 生成容器的同时,删除不必要的容器。
        /// </summary>
        /// <param name="children"></param>
        /// <param name="generator"></param>
        private void RealizeWithCleanup(UIElementCollection children, IItemContainerGenerator generator)
        {
            //注意,此模式下会有拖动列头顺序时,单元格子不变化的问题。由于暂时不使用此模式,所以暂时先不完成。

            // 获取第一个可视元素位置信息
            var start = generator.GeneratorPositionFromIndex(this._from);
            // 根据元素位置信息计算子元素索引
            int childIndex = start.Offset == 0 ? start.Index : start.Index + 1;
            using (generator.StartAt(start, GeneratorDirection.Forward, true))
            {
                for (int i = this._from; i <= this._to; i++, childIndex++)
                {
                    bool isNewlyRealized;
                    var container = generator.GenerateNext(out isNewlyRealized) as UIElement;
                    if (isNewlyRealized)
                    {
                        if (childIndex >= children.Count)
                        {
                            this.AddInternalChild(container);
                        }
                        else
                        {
                            this.InsertInternalChild(childIndex, container);
                        }
                        generator.PrepareItemContainer(container);
                    }
                }
            }

            this.Cleanup(children, generator);
        }
        private void CleanupRange(IList children, IItemContainerGenerator generator, int startIndex, int count)
        { 
            if (InRecyclingMode) 
            {
                Debug.Assert(startIndex >= 0 && count > 0); 
                Debug.Assert(children == _realizedChildren, "the given child list must be the _realizedChildren list when recycling");
                ((IRecyclingItemContainerGenerator)generator).Recycle(new GeneratorPosition(startIndex, 0), count);

                // The call to Recycle has caused the ItemContainerGenerator to remove some items 
                // from its list of realized items; we adjust _realizedChildren to match.
                _realizedChildren.RemoveRange(startIndex, count); 
            } 
            else
            { 
                // Remove the desired range of children
                VirtualizingPanel.RemoveInternalChildRange((UIElementCollection)children, startIndex, count);
                generator.Remove(new GeneratorPosition(startIndex, 0), count);
            } 

            AdjustFirstVisibleChildIndex(startIndex, count); 
        } 
        private void ArrangeItemsBeyondTheExtendedViewport(
            bool isHorizontal,
            UIElement child,
            Size childDesiredSize,
            double arrangeLength,
            IList items,
            IItemContainerGenerator generator,
            IContainItemStorage itemStorageProvider,
            bool areContainersUniformlySized,
            double uniformOrAverageContainerSize,
            bool beforeExtendedViewport,
            ref Rect rcChild,
            ref Size previousChildSize,
            ref Point previousChildOffset,
            ref int previousChildItemIndex)
        {
            //
            // These are the items beyond the viewport. (Eg. Recyclable containers that
            // are waiting until next measure to be cleaned up, Elements that are kept
            // alive because they hold focus.) These element are arranged beyond the
            // visible viewport but at their right position. This is important because these
            // containers need to be brought into view when using keyboard navigation
            // and their arrange rect is what informs the scroillviewer of the right offset
            // to scroll to.
            //
            if (isHorizontal)
            {
                rcChild.Width = childDesiredSize.Width;
                rcChild.Height = Math.Max(arrangeLength, childDesiredSize.Height);

                if (IsPixelBased)
                {
                    int currChildItemIndex = ((ItemContainerGenerator)generator).IndexFromContainer(child, true /*returnLocalIndex*/);
                    double distance;

                    if (beforeExtendedViewport)
                    {
                        if (previousChildItemIndex == -1)
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, 0, currChildItemIndex, out distance);
                        }
                        else
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, currChildItemIndex, previousChildItemIndex-currChildItemIndex, out distance);
                        }

                        rcChild.X = previousChildOffset.X - distance;
                        rcChild.Y = previousChildOffset.Y;
                    }
                    else
                    {
                        if (previousChildItemIndex == -1)
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, 0, currChildItemIndex, out distance);
                        }
                        else
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, previousChildItemIndex, currChildItemIndex-previousChildItemIndex, out distance);
                        }

                        rcChild.X = previousChildOffset.X + distance;
                        rcChild.Y = previousChildOffset.Y;
                    }

                    previousChildItemIndex = currChildItemIndex;
                }
                else
                {
                    if (beforeExtendedViewport)
                    {
                        rcChild.X -= childDesiredSize.Width;
                    }
                    else
                    {
                        rcChild.X += previousChildSize.Width;
                    }
                }
            }
            else
            {
                rcChild.Height = childDesiredSize.Height;
                rcChild.Width = Math.Max(arrangeLength, childDesiredSize.Width);

                if (IsPixelBased)
                {
                    int currChildItemIndex = ((ItemContainerGenerator)generator).IndexFromContainer(child, true /*returnLocalIndex*/);
                    double distance;

                    if (beforeExtendedViewport)
                    {
                        if (previousChildItemIndex == -1)
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, 0, currChildItemIndex, out distance);
                        }
                        else
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, currChildItemIndex, previousChildItemIndex-currChildItemIndex, out distance);
                        }

                        rcChild.Y = previousChildOffset.Y - distance;
                        rcChild.X = previousChildOffset.X;
                    }
                    else
                    {
                        if (previousChildItemIndex == -1)
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, 0, currChildItemIndex, out distance);
                        }
                        else
                        {
                            ComputeDistance(items, itemStorageProvider, isHorizontal, areContainersUniformlySized, uniformOrAverageContainerSize, previousChildItemIndex, currChildItemIndex-previousChildItemIndex, out distance);
                        }

                        rcChild.Y = previousChildOffset.Y + distance;
                        rcChild.X = previousChildOffset.X;
                    }

                    previousChildItemIndex = currChildItemIndex;
                }
                else
                {
                    if (beforeExtendedViewport)
                    {
                        rcChild.Y -= childDesiredSize.Height;
                    }
                    else
                    {
                        rcChild.Y += previousChildSize.Height;
                    }
                }
            }

            previousChildSize = childDesiredSize;
            previousChildOffset = rcChild.Location;

            child.Arrange(rcChild);
        }