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 }); }
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(); }
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); }
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); }
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); } }
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); } } }
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); }
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); }
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(); } } } }