protected internal override void OnQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            base.OnQueryItems(page, queryInfo);

            DataGridVirtualizingQueryableCollectionViewGroup collectionViewGroup =
                this.GetLinkedCollectionViewGroup(page.ParentVirtualList) as DataGridVirtualizingQueryableCollectionViewGroup;

            IQueryable queryableToUse;

            int virtualItemCount = collectionViewGroup.VirtualItemCount;

            bool queryableIsReversed;

            if ((!m_supportsPrimaryKeyOptimizations) || (queryInfo.StartIndex < (virtualItemCount / 2)))
            {
                queryableIsReversed = false;
                queryableToUse      = collectionViewGroup.Queryable.Slice(queryInfo.StartIndex, queryInfo.RequestedItemCount);
            }
            else
            {
                queryableIsReversed = true;

                int reversedStartIndex = virtualItemCount - (queryInfo.StartIndex + queryInfo.RequestedItemCount);

                queryableToUse = collectionViewGroup.ReversedQueryable.Slice(reversedStartIndex, queryInfo.RequestedItemCount);
            }

            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(this.AsyncGatherItems), new object[] { queryInfo, queryableToUse, queryableIsReversed });
        }
Exemple #2
0
        private VirtualPage CreateNewPage(int itemIndex)
        {
            Debug.Assert(!m_tableOfContent.ContainsPageForSourceIndex(itemIndex));

            int pageStartIndex = this.GetPageStartingIndexForItemIndex(itemIndex);

            int pageSize = m_pagingManager.PageSize;

            int expectedItemCount = System.Math.Min(pageSize, (m_virtualCount - pageStartIndex));

            expectedItemCount = System.Math.Max(0, expectedItemCount);

            VirtualPage page = VirtualPage.CreateEmptyPage(this, pageStartIndex, expectedItemCount);

            m_tableOfContent.AddPage(page);

            // If we have a pending commit page, this brandly new created page will get its query data queued when we are notified
            // of a commit completed and that we no longer have any pages awaiting commiting.
            if (!this.HasPagePendingCommit)
            {
                m_pagingManager.QueueQueryData(page);
            }

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Creating VirtualItemPlaceHolder for page: " + page.ToString());
            return(page);
        }
        internal void RemovePage(VirtualPage page)
        {
            if (page.IsDisposed)
            {
                return;
            }

            Debug.Assert(page != null);
            //Debug.Assert( !page.IsRestarting );

            Debug.Assert(!page.IsDirty);

            // A filled page is being removed.  Change the version.
            this.IncrementVersion();

            // Update the table of content of the page's ParentVirtualList
            page.ParentVirtualList.TableOfContent.RemovePage(page);

            m_pageNodes.Remove(page);

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Removed Page: " + page.ToString());

            // Dispose the page since it will never be reused
            page.Dispose();
        }
Exemple #4
0
        internal static VirtualPage CreateEmptyPage(VirtualList parentVirtualList, int startSourceIndex, int entryCount)
        {
            if (parentVirtualList == null)
            {
                throw new ArgumentNullException("parentVirtualList");
            }

            if (startSourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException("startSourceIndex", startSourceIndex, "startSourceIndex must be greater than or equal to zero.");
            }

            if (entryCount < 0)
            {
                throw new ArgumentOutOfRangeException("entryCount", entryCount, "entryCount must be greater than or equal to zero.");
            }

            EmptyDataItem[] emptyDataItems = new EmptyDataItem[entryCount];
            for (int i = 0; i < entryCount; i++)
            {
                emptyDataItems[i] = new EmptyDataItem(startSourceIndex + i, parentVirtualList);
            }

            VirtualPage emptyDataItemPage = new VirtualPage(parentVirtualList, startSourceIndex, emptyDataItems);

            emptyDataItemPage.IsFilled = false;

            return(emptyDataItemPage);
        }
Exemple #5
0
 internal void OnVirtualPageRestarting(VirtualPage page)
 {
     // Notify the VirtualPageManager that this page is restarted
     // to ensure it commits its data or aborts the QueryItems
     // if already invoked
     Debug.Assert(m_restartingPages.Contains(page));
     m_pagingManager.OnVirtualListPageRestarting(this, page);
 }
        protected internal override void OnQueryItemsCompleted(VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            base.OnQueryItemsCompleted(page, queryInfo, fetchedItems);

            Debug.Assert(m_asyncQueryInfosInProgress.Contains(queryInfo));
            m_asyncQueryInfosInProgress.Remove(queryInfo);

            this.UpdateConnectionState();
        }
        private void RaiseCollectionViewOnCommitItems(VirtualPage dispatchedPage, AsyncCommitInfo dispatchedCommitInfo)
        {
            DataGridVirtualizingCollectionViewBase collectionView = this.CollectionView as DataGridVirtualizingCollectionViewBase;

            DataGridVirtualizingCollectionViewGroupBase collectionViewGroup =
                this.GetLinkedCollectionViewGroup(dispatchedPage.ParentVirtualList) as DataGridVirtualizingCollectionViewGroupBase;

            Debug.Assert((collectionViewGroup != null) && (collectionView != null));

            collectionView.OnCommitItems(dispatchedCommitInfo);
        }
        internal virtual void OnVirtualListPageRestarting(VirtualList virtualList, VirtualPage page)
        {
            Debug.Assert(m_managedLists.Contains(virtualList));

            LinkedListNode <VirtualPage> pageNode = m_pageNodes.Find(page);

            Debug.Assert(pageNode != null);

            // RemovePageNode takes care of either raising the AbortQueryData event or aborting the QueryData Dispatcher Operation altogether.
            // It also takes care of raising the CommitVirtualData event for loaded pages which contains modified data.
            this.QueueCommitDataOrAbortIfRequired(pageNode, false);
        }
        public bool TryGetPageForItem(object item, out VirtualPage page)
        {
            page = null;

            int index;

            if (m_objectVersusIndexDictionary.TryGetValue(item, out index))
            {
                return(m_indexVersusPageDictionary.TryGetValue(index, out page));
            }

            return(false);
        }
        internal void QueueCommitData(VirtualPage page)
        {
            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "QueueCommitData for page " + page.ToString());
            Debug.Assert(m_managedLists.Contains(page.ParentVirtualList));
            Debug.Assert(page.IsFilled);
            Debug.Assert(page.IsDirty);

            if (this.RestartingManager)
            {
                this.ShouldRefreshAfterRestart = true;
            }

            page.QueueCommitData(this.Dispatcher);
        }
Exemple #11
0
        private VirtualPage GetPageOrDefaultForItemIndex(int index, bool preventMoveToFront)
        {
            VirtualPage page = null;

            if (m_tableOfContent.TryGetPageForSourceIndex(index, out page))
            {
                if (!preventMoveToFront)
                {
                    m_pagingManager.MovePageToFront(page);
                }
            }

            return(page);
        }
        protected internal override void OnQueryItemsCompleted(VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;

            // The VirtualPageManager was Disposed
            if (collectionView == null)
            {
                return;
            }

            using (collectionView.DeferRefresh())
            {
                base.OnQueryItemsCompleted(page, queryInfo, fetchedItems);
            }
        }
Exemple #13
0
        private void PreEmptiveLoadPages(int sourceIndex, VirtualPage page)
        {
            // The VirtualList is disposed or part of a PagingManager
            // that will be disposed (only disconnected when dispose is required)
            if (!this.PagingManager.IsConnected)
            {
                return;
            }

            Debug.Assert(!this.IsDisposed);

            double preemptivePageQueryRatio = m_pagingManager.PreemptivePageQueryRatio;
            int    pageSize = m_pagingManager.PageSize;

            double pageRatio = (preemptivePageQueryRatio > 0.5) ? 0.5 :
                               (preemptivePageQueryRatio < 0.0) ? 0 : preemptivePageQueryRatio;

            double boundariesItemCount = (pageRatio * pageSize);

            int preEmptivePageStartIndex = -1;

            if ((page.StartDataIndex > 0) && (sourceIndex < (page.StartDataIndex + boundariesItemCount)))
            {
                // Pre emptively load the previous page.
                preEmptivePageStartIndex = page.StartDataIndex - pageSize;
            }
            else if ((page.EndDataIndex < (m_virtualCount - 1)) && (sourceIndex > (page.EndDataIndex - boundariesItemCount)))
            {
                // Pre emptively load the next page.
                preEmptivePageStartIndex = page.EndDataIndex + 1;
            }

            if (preEmptivePageStartIndex != -1)
            {
                VirtualPage preEmptivePage = null;

                // We do not want to move the pre-emptive page to the front if it is already created since it does not count as a
                // legitimate user-acess.
                preEmptivePage = this.GetPageOrDefaultForItemIndex(preEmptivePageStartIndex, true);

                if (preEmptivePage == null)
                {
                    // The pre-emptive page is not yet created. Let's do it and add it to the back since it is not really accessed at the moment.
                    preEmptivePage = this.CreateNewPage(preEmptivePageStartIndex);
                    m_pagingManager.AddPage(preEmptivePage, VirtualPageManager.PageInsertPosition.Back);
                }
            }
        }
Exemple #14
0
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();

            ReadOnlyCollection <VirtualPage> virtualPages = m_tableOfContent.VirtualPages;
            int pageCount = virtualPages.Count;

            for (int i = 0; i < pageCount; i++)
            {
                VirtualPage page = virtualPages[i];

                builder.Append(i.ToString() + ": Page " + page.ToString() + Environment.NewLine);
            }

            return(builder.ToString());
        }
        protected internal override void OnAbortQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;

            // The VirtualPageManager was Disposed
            if (collectionView == null)
            {
                return;
            }

            DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup(page.ParentVirtualList) as DataGridVirtualizingCollectionViewGroup;

            collectionView.OnAbortQueryItems(queryInfo, collectionViewGroup);

            base.OnAbortQueryItems(page, queryInfo);
        }
        protected internal override void OnAbortQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            base.OnAbortQueryItems(page, queryInfo);

            // It is possible that the queryInfo was removed previously
            m_asyncQueryInfosInProgress.Remove(queryInfo);

            // In case the page query was aborted when
            // VirtualPageManager.CleanUpUnused is called
            if (page.RemoveAfterOperation)
            {
                this.RemovePage(page);
            }

            this.UpdateConnectionState();
        }
        protected internal override void OnBuiltInAbort(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            // When a built-in abort occurs, we ensure to remove
            // any AsyncQueryInfo from references since the ConnectionState
            // use this array to update its actual state
            m_asyncQueryInfosInProgress.Remove(queryInfo);

            // In case the page query was aborted when
            // VirtualPageManager.CleanUpUnused is called
            if (page.RemoveAfterOperation)
            {
                this.RemovePage(page);
            }

            this.UpdateConnectionState();
        }
        protected internal override void OnCommitItemsCompleted(VirtualPage page, AsyncCommitInfo commitInfo)
        {
            Debug.Assert(m_asyncCommitInfosInProgress.Contains(commitInfo));
            m_asyncCommitInfosInProgress.Remove(commitInfo);
            this.UpdateConnectionState();

            base.OnCommitItemsCompleted(page, commitInfo);

            // In case the page query was aborted when
            // VirtualPageManager.CleanUpUnused is called
            if (page.RemoveAfterOperation)
            {
                this.RemovePage(page);
            }

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "OnCommitItemsCompleted for page " + page.ToString());
        }
        protected internal override void OnCommitItems(VirtualPage page, AsyncCommitInfo commitInfo)
        {
            base.OnCommitItems(page, commitInfo);

            Debug.Assert(!m_asyncCommitInfosInProgress.Contains(commitInfo));
            m_asyncCommitInfosInProgress.Add(commitInfo);

            this.UpdateConnectionState();

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "OnCommitItems for page " + page.ToString());

            m_collectionView.Dispatcher.BeginInvoke(
                new Action <VirtualPage, AsyncCommitInfo>(this.RaiseCollectionViewOnCommitItems),
                DispatcherPriority.Background,
                page,
                commitInfo);
        }
        internal void MovePageToFront(VirtualPage page)
        {
            // The further from the front a page is, the longer it has been since it was requested.
            Debug.Assert(page != null);

            LinkedListNode <VirtualPage> firstNode = m_pageNodes.First;

            if (firstNode.Value != page)
            {
                LinkedListNode <VirtualPage> node = m_pageNodes.Find(page);

                m_pageNodes.Remove(node);
                m_pageNodes.AddFirst(node);

                Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Moved To Front: Page " + page.ToString());
            }
        }
        public void Dispose()
        {
            while (m_virtualPages.Count > 0)
            {
                // Remove the page from every Dictionaries and
                // also from m_virtualPages
                VirtualPage page = m_virtualPages[0];
                this.RemovePage(page);
                page.Dispose();
            }

            Debug.Assert(m_objectVersusIndexDictionary.Count == 0);
            Debug.Assert(m_indexVersusPageDictionary.Count == 0);
            Debug.Assert(m_virtualPages.Count == 0);

            m_objectVersusIndexDictionary.Clear();
            m_indexVersusPageDictionary.Clear();
            m_virtualPages.Clear();
        }
        public void AddPage(VirtualPage page)
        {
            Debug.Assert(!m_virtualPages.Contains(page));

            m_virtualPages.Add(page);

            int itemCount = page.Count;

            for (int i = 0; i < itemCount; i++)
            {
                VirtualizedItemInfo virtualizedItemInfo = page[i];

                Debug.Assert(!m_objectVersusIndexDictionary.ContainsKey(virtualizedItemInfo.DataItem));
                Debug.Assert(!m_indexVersusPageDictionary.ContainsKey(virtualizedItemInfo.Index));

                m_objectVersusIndexDictionary.Add(virtualizedItemInfo.DataItem, virtualizedItemInfo.Index);
                m_indexVersusPageDictionary.Add(virtualizedItemInfo.Index, page);
            }
        }
        protected internal override void OnQueryErrorChanged(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            base.OnQueryErrorChanged(page, queryInfo);

            // It is possible that m_asyncQueryInfosInProgress does not contain the queryInfo when
            // the query was aborted but the user did not stop the query and later on set the queryInfo error
            // event if the queryInfo ShouldAbort is set to True.
            Debug.Assert((m_asyncQueryInfosInProgress.Contains(queryInfo)) || (queryInfo.ShouldAbort));

            object error = queryInfo.Error;

            if (error == null)
            {
                // Even if the queryInfo's ShouldAbort property is set to True, clean-up the error.
                Debug.Assert((m_asyncQueryInfosInError != null) && (m_asyncQueryInfosInError.Contains(queryInfo)));

                m_asyncQueryInfosInError.Remove(queryInfo);

                if (m_asyncQueryInfosInError.Count == 0)
                {
                    m_asyncQueryInfosInError = null;
                }
            }
            else if (!queryInfo.ShouldAbort)
            {
                // Only add errors if the queryInfo's ShouldAbort property is set to False.
                if (m_asyncQueryInfosInError == null)
                {
                    m_asyncQueryInfosInError = new LinkedList <AsyncQueryInfo>();
                }

                if (m_asyncQueryInfosInError.Contains(queryInfo))
                {
                    m_asyncQueryInfosInError.Remove(queryInfo);
                }

                m_asyncQueryInfosInError.AddFirst(queryInfo);
            }

            this.UpdateConnectionState();
        }
        public void RemovePage(VirtualPage page)
        {
            Debug.Assert(m_virtualPages.Contains(page));

            int itemCount = page.Count;

            for (int i = 0; i < itemCount; i++)
            {
                VirtualizedItemInfo virtualizedItemInfo = page[i];

                Debug.Assert(m_objectVersusIndexDictionary.ContainsKey(virtualizedItemInfo.DataItem));
                Debug.Assert(m_indexVersusPageDictionary.ContainsKey(virtualizedItemInfo.Index));

                Debug.Assert(m_indexVersusPageDictionary[virtualizedItemInfo.Index] == page);

                m_objectVersusIndexDictionary.Remove(virtualizedItemInfo.DataItem);
                m_indexVersusPageDictionary.Remove(virtualizedItemInfo.Index);
            }

            m_virtualPages.Remove(page);
        }
Exemple #25
0
        internal VirtualizedItemInfo GetVirtualizedItemInfoAtIndex(int index, bool createPageIfLineNotFound, bool preventMovePageToFront)
        {
            VirtualizedItemInfo virtualizedItemInfo = null;

            VirtualPage page = this.GetPageOrDefaultForItemIndex(index, preventMovePageToFront);

            if (page != null)
            {
                virtualizedItemInfo = page.GetVirtualizedItemInfoAtIndex(index);

                Debug.Assert(virtualizedItemInfo != null);


                //if( ( virtualizedItemInfo == null ) && ( createPageIfLineNotFound ) )
                //{
                //  // No VirtualizedItemInfo was found at the requested index.
                //  LinkedListNode<VirtualPage> firstPageNode = m_pageNodes.First;

                //  Debug.Assert( firstPageNode != null, "If the page is not null, there should be at least one page in the book." );

                //  if( firstPageNode.Value != page )
                //  {
                //
                //    page = this.CreateNewPage( index );

                //    virtualizedItemInfo = page.GetVirtualizedItemInfoAtIndex( index );
                //    this.AddPageToFront( page );
                //  }
                //}
            }
            else if (createPageIfLineNotFound)
            {
                page = this.CreateNewPage(index);

                virtualizedItemInfo = page.GetVirtualizedItemInfoAtIndex(index);
                m_pagingManager.AddPage(page, VirtualPageManager.PageInsertPosition.Front);
            }

            return(virtualizedItemInfo);
        }
        private void QueueCommitDataOrAbortIfRequired(
            LinkedListNode <VirtualPage> pageNode,
            bool removeAfterOperation)
        {
            VirtualPage page = pageNode.Value;

            // Update the flag in case this page must be removed
            // after an abort or commit operation
            page.RemoveAfterOperation = removeAfterOperation;

            // The only circumstance when we should remove a page which is not removable is if we are restarting.
            Debug.Assert((page != null) &&
                         (!page.IsDisposed) &&
                         ((page.IsRemovable) || (page.ParentVirtualList.IsRestarting)));

            if (page.IsDirty)
            {
                // Don't remove pages which contains modifications.  We'll remove them from the book when they are committed, if they
                // aren't locked.
                this.QueueCommitData(page);
            }
            else if (!page.IsFilled)
            {
                // The page is not filled, we must send abort
                // the QueryData for this page in case it was sent
                page.AbortQueryDataOperation();
            }

            // The page must be removed after operation
            // and it has nothing to commit and is not
            // currently aborting an operation. It is safe
            // to remove it
            if (removeAfterOperation &&
                !page.IsCommitPending &&
                !page.IsAborting)
            {
                this.RemovePage(page);
            }
        }
        internal void AddPage(VirtualPage page, PageInsertPosition insertPosition)
        {
            if (page == null)
            {
                throw new ArgumentNullException("page", "TODOOC: An internal error occured while paging data. Page cannot be null.");
            }

            // We call clean-up before the call to AddFirst since if we do
            // it afterward and the page is pending fill, we will remove it.
            this.CleanUpAndDisposeUnused();

            if (insertPosition == PageInsertPosition.Front)
            {
                m_pageNodes.AddFirst(page);
            }
            else
            {
                m_pageNodes.AddLast(page);
            }

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Added To " + ((insertPosition == PageInsertPosition.Front) ? "Front" : "Back") + ": Page " + page.ToString());
        }
        internal List <LinkedListNode <VirtualPage> > GetUnlockedPendingFillNodes()
        {
            List <LinkedListNode <VirtualPage> > unlockedPendingFillNodes = new List <LinkedListNode <VirtualPage> >();

            LinkedListNode <VirtualPage> lastUnlockedPendingFillNode = m_pageNodes.Last;

            while (lastUnlockedPendingFillNode != null)
            {
                VirtualPage page = lastUnlockedPendingFillNode.Value;

                Debug.Assert(page != null);

                if ((!page.IsLocked) && (!page.IsFilled))
                {
                    unlockedPendingFillNodes.Add(lastUnlockedPendingFillNode);
                }

                lastUnlockedPendingFillNode = lastUnlockedPendingFillNode.Previous;
            }

            return(unlockedPendingFillNodes);
        }
        private int GetRemovablePageItemCount()
        {
            int removablePageItemCount = 0;

            LinkedListNode <VirtualPage> pageNode = m_pageNodes.Last;

            while (pageNode != null)
            {
                VirtualPage page = pageNode.Value;

                Debug.Assert(page != null);

                if ((page != null) && (page.IsRemovable))
                {
                    removablePageItemCount += page.Count;
                }

                pageNode = pageNode.Previous;
            }

            return(removablePageItemCount);
        }
Exemple #30
0
        internal void Restart()
        {
            if (this.IsRestarting)
            {
                return;
            }

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Restart VirtualList requested, checking for pages to commit or abort...");
            this.IsRestarting = true;
            m_pagingManager.OnVirtualListRestarting(this);

            // We must keep a copy since restarting can remove pages from table of content
            int virtualPagesCount = m_tableOfContent.VirtualPages.Count;

            if (virtualPagesCount == 0)
            {
                this.EndRestart();
            }
            else
            {
                // Restart every pages this VirtualList contains

                // Keep a reference to the pages that need to restart
                // in order to know when this VirtualList is restarted
                m_restartingPages.AddRange(m_tableOfContent.VirtualPages);

                for (int i = virtualPagesCount - 1; i >= 0; i--)
                {
                    VirtualPage page = m_tableOfContent.VirtualPages[i];
                    Debug.Assert(!page.IsDisposed);

                    if (!page.IsRestarting)
                    {
                        page.Restart();
                    }
                }
            }
        }