/// <summary> /// Recalculates the control layout. /// <param name="forceUpdate">true to force an update; otherwise false.</param> /// </summary> public void Update(bool forceUpdate) { if (mImageListView.ClientRectangle.Width == 0 || mImageListView.ClientRectangle.Height == 0) return; // If only item order is changed, just update visible items. if (!forceUpdate && !UpdateRequired && mImageListView.Items.collectionModified) { UpdateGroups(); UpdateVisibleItems(); return; } if (!forceUpdate && !UpdateRequired) return; // Get the item size from the renderer mItemSize = mImageListView.mRenderer.MeasureItem(mImageListView.View); cachedItemMargin = mImageListView.mRenderer.MeasureItemMargin(mImageListView.View); mItemSizeWithMargin = mItemSize + cachedItemMargin; // Cache current properties to determine if we will need an update later bool viewChanged = (cachedView != mImageListView.View); cachedView = mImageListView.View; cachedViewOffset = mImageListView.ViewOffset; cachedSize = mImageListView.ClientSize; cachedItemCount = mImageListView.Items.Count; cachedIntegralScroll = mImageListView.IntegralScroll; cachedItemSize = mItemSize; cachedGroupHeaderHeight = mImageListView.mRenderer.MeasureGroupHeaderHeight(); cachedColumnHeaderHeight = mImageListView.mRenderer.MeasureColumnHeaderHeight(); cachedPaneWidth = mImageListView.PaneWidth; cachedScrollBars = mImageListView.ScrollBars; mImageListView.Items.collectionModified = false; mImageListView.groups.collectionModified = false; // Calculate item area bounds if (!UpdateItemArea()) return; // Let the calculated bounds modified by the renderer LayoutEventArgs eLayout = new LayoutEventArgs(mItemAreaBounds); mImageListView.mRenderer.OnLayout(eLayout); mItemAreaBounds = eLayout.ItemAreaBounds; if (mItemAreaBounds.Width <= 0 || mItemAreaBounds.Height <= 0) return; // Calculate the number of rows and columns CalculateGrid(); // Update groups UpdateGroups(); // Check if we need the scroll bars. // Recalculate the layout if scroll bar visibility changes. if (CheckScrollBars()) { Update(true); return; } // Update scroll range UpdateScrollBars(); // Cache visible items UpdateVisibleItems(); // Recalculate the layout if view mode was changed if (viewChanged) Update(); }
/// <summary> /// Recalculates the control layout. /// </summary> public void Update(bool forceUpdate) { if (mImageListView.ClientRectangle.Width == 0 || mImageListView.ClientRectangle.Height == 0) return; if (!forceUpdate && !UpdateRequired) return; // Cache current properties to determine if we will need an update later cachedView = mImageListView.View; cachedViewOffset = mImageListView.ViewOffset; cachedSize = mImageListView.ClientSize; cachedItemCount = mImageListView.Items.Count; cachedItemSize = mImageListView.mRenderer.MeasureItem(mImageListView.View); cachedHeaderHeight = mImageListView.mRenderer.MeasureColumnHeaderHeight(); cachedItemMargin = mImageListView.mRenderer.MeasureItemMargin(mImageListView.View); cachedPaneWidth = mImageListView.PaneWidth; cachedScrollBars = mImageListView.ScrollBars; cachedVisibleItems.Clear(); // Calculate drawing area mClientArea = mImageListView.ClientRectangle; mItemAreaBounds = mImageListView.ClientRectangle; // Item size mItemSize = cachedItemSize; mItemSizeWithMargin = mItemSize + cachedItemMargin; // Allocate space for scrollbars if (mImageListView.hScrollBar.Visible) { mClientArea.Height -= mImageListView.hScrollBar.Height; mItemAreaBounds.Height -= mImageListView.hScrollBar.Height; } if (mImageListView.vScrollBar.Visible) { mClientArea.Width -= mImageListView.vScrollBar.Width; mItemAreaBounds.Width -= mImageListView.vScrollBar.Width; } // Allocate space for column headers if (mImageListView.View == View.Details) { int headerHeight = cachedHeaderHeight; // Location of the column headers mColumnHeaderBounds.X = mClientArea.Left - mImageListView.ViewOffset.X; mColumnHeaderBounds.Y = mClientArea.Top; mColumnHeaderBounds.Height = headerHeight; mColumnHeaderBounds.Width = mClientArea.Width + mImageListView.ViewOffset.X; mItemAreaBounds.Y += headerHeight; mItemAreaBounds.Height -= headerHeight; } else { mColumnHeaderBounds = Rectangle.Empty; } // Modify item area for the gallery view mode if (mImageListView.View == View.Gallery) { mItemAreaBounds.Height = mItemSizeWithMargin.Height; mItemAreaBounds.Y = mClientArea.Bottom - mItemSizeWithMargin.Height; } // Modify item area for the pane view mode if (mImageListView.View == View.Pane) { mItemAreaBounds.Width -= cachedPaneWidth; mItemAreaBounds.X += cachedPaneWidth; } if (mItemAreaBounds.Width < 1 || mItemAreaBounds.Height < 1) return; // Let the calculated bounds modified by the renderer LayoutEventArgs eLayout = new LayoutEventArgs(mItemAreaBounds); mImageListView.mRenderer.OnLayout(eLayout); mItemAreaBounds = eLayout.ItemAreaBounds; // Maximum number of rows and columns that can be fully displayed mCols = (int)System.Math.Floor((float)mItemAreaBounds.Width / (float)mItemSizeWithMargin.Width); mRows = (int)System.Math.Floor((float)mItemAreaBounds.Height / (float)mItemSizeWithMargin.Height); if (mImageListView.View == View.Details) mCols = 1; if (mImageListView.View == View.Gallery) mRows = 1; if (mCols < 1) mCols = 1; if (mRows < 1) mRows = 1; // Check if we need the horizontal scroll bar bool hScrollRequired = false; if (mImageListView.ScrollBars) { if (mImageListView.View == View.Gallery) hScrollRequired = (mImageListView.Items.Count > 0) && (mCols * mRows < mImageListView.Items.Count); else hScrollRequired = (mImageListView.Items.Count > 0) && (mItemAreaBounds.Width < mCols * mItemSizeWithMargin.Width); } if (hScrollRequired != hScrollVisible) { hScrollVisible = hScrollRequired; mImageListView.hScrollBar.Visible = hScrollRequired; Update(true); return; } // Check if we need the vertical scroll bar bool vScrollRequired = false; if (mImageListView.ScrollBars) { if (mImageListView.View == View.Gallery) vScrollRequired = (mImageListView.Items.Count > 0) && (mItemAreaBounds.Height < mRows * mItemSizeWithMargin.Height); else vScrollRequired = (mImageListView.Items.Count > 0) && (mCols * mRows < mImageListView.Items.Count); } if (vScrollRequired != vScrollVisible) { vScrollVisible = vScrollRequired; mImageListView.vScrollBar.Visible = vScrollRequired; Update(true); return; } // Horizontal scroll range if (mImageListView.View == View.Gallery) { mImageListView.hScrollBar.SmallChange = mItemSizeWithMargin.Width; mImageListView.hScrollBar.LargeChange = mItemSizeWithMargin.Width * (mItemAreaBounds.Width / mItemSizeWithMargin.Width); mImageListView.hScrollBar.Minimum = 0; mImageListView.hScrollBar.Maximum = Math.Max(0, (int)System.Math.Ceiling((float)mImageListView.Items.Count / (float)mRows) * mItemSizeWithMargin.Width - 1); } else { mImageListView.hScrollBar.SmallChange = 1; mImageListView.hScrollBar.LargeChange = mItemAreaBounds.Width; mImageListView.hScrollBar.Minimum = 0; mImageListView.hScrollBar.Maximum = mCols * mItemSizeWithMargin.Width; } if (mImageListView.ViewOffset.X > mImageListView.hScrollBar.Maximum - mImageListView.hScrollBar.LargeChange + 1) { mImageListView.hScrollBar.Value = mImageListView.hScrollBar.Maximum - mImageListView.hScrollBar.LargeChange + 1; mImageListView.ViewOffset = new Point(mImageListView.hScrollBar.Value, mImageListView.ViewOffset.Y); } // Vertical scroll range if (mImageListView.View == View.Gallery) { mImageListView.vScrollBar.SmallChange = 1; mImageListView.vScrollBar.LargeChange = mItemAreaBounds.Height; mImageListView.vScrollBar.Minimum = 0; mImageListView.vScrollBar.Maximum = mRows * mItemSizeWithMargin.Height; } else { mImageListView.vScrollBar.SmallChange = mItemSizeWithMargin.Height; mImageListView.vScrollBar.LargeChange = mItemSizeWithMargin.Height * (mItemAreaBounds.Height / mItemSizeWithMargin.Height); mImageListView.vScrollBar.Minimum = 0; mImageListView.vScrollBar.Maximum = Math.Max(0, (int)System.Math.Ceiling((float)mImageListView.Items.Count / (float)mCols) * mItemSizeWithMargin.Height - 1); } if (mImageListView.ViewOffset.Y > mImageListView.vScrollBar.Maximum - mImageListView.vScrollBar.LargeChange + 1) { mImageListView.vScrollBar.Value = mImageListView.vScrollBar.Maximum - mImageListView.vScrollBar.LargeChange + 1; mImageListView.ViewOffset = new Point(mImageListView.ViewOffset.X, mImageListView.vScrollBar.Value); } // Zero out the scrollbars if we don't have any items if (mImageListView.Items.Count == 0) { mImageListView.hScrollBar.Minimum = 0; mImageListView.hScrollBar.Maximum = 0; mImageListView.hScrollBar.Value = 0; mImageListView.vScrollBar.Minimum = 0; mImageListView.vScrollBar.Maximum = 0; mImageListView.vScrollBar.Value = 0; mImageListView.ViewOffset = new Point(0, 0); } // Horizontal scrollbar position mImageListView.hScrollBar.Left = 0; mImageListView.hScrollBar.Top = mImageListView.ClientRectangle.Bottom - mImageListView.hScrollBar.Height; mImageListView.hScrollBar.Width = mImageListView.ClientRectangle.Width - (mImageListView.vScrollBar.Visible ? mImageListView.vScrollBar.Width : 0); // Vertical scrollbar position mImageListView.vScrollBar.Left = mImageListView.ClientRectangle.Right - mImageListView.vScrollBar.Width; mImageListView.vScrollBar.Top = 0; mImageListView.vScrollBar.Height = mImageListView.ClientRectangle.Height - (mImageListView.hScrollBar.Visible ? mImageListView.hScrollBar.Height : 0); // Find the first and last partially visible items if (mImageListView.View == View.Gallery) { mFirstPartiallyVisible = (int)System.Math.Floor((float)mImageListView.ViewOffset.X / (float)mItemSizeWithMargin.Width) * mRows; mLastPartiallyVisible = (int)System.Math.Ceiling((float)(mImageListView.ViewOffset.X + mItemAreaBounds.Width) / (float)mItemSizeWithMargin.Width) * mRows - 1; } else { mFirstPartiallyVisible = (int)System.Math.Floor((float)mImageListView.ViewOffset.Y / (float)mItemSizeWithMargin.Height) * mCols; mLastPartiallyVisible = (int)System.Math.Ceiling((float)(mImageListView.ViewOffset.Y + mItemAreaBounds.Height) / (float)mItemSizeWithMargin.Height) * mCols - 1; } if (mFirstPartiallyVisible < 0) mFirstPartiallyVisible = 0; if (mFirstPartiallyVisible > mImageListView.Items.Count - 1) mFirstPartiallyVisible = mImageListView.Items.Count - 1; if (mLastPartiallyVisible < 0) mLastPartiallyVisible = 0; if (mLastPartiallyVisible > mImageListView.Items.Count - 1) mLastPartiallyVisible = mImageListView.Items.Count - 1; // Find the first and last visible items if (mImageListView.View == View.Gallery) { mFirstVisible = (int)System.Math.Ceiling((float)mImageListView.ViewOffset.X / (float)mItemSizeWithMargin.Width) * mRows; mLastVisible = (int)System.Math.Floor((float)(mImageListView.ViewOffset.X + mItemAreaBounds.Width) / (float)mItemSizeWithMargin.Width) * mRows - 1; } else { mFirstVisible = (int)System.Math.Ceiling((float)mImageListView.ViewOffset.Y / (float)mItemSizeWithMargin.Height) * mCols; mLastVisible = (int)System.Math.Floor((float)(mImageListView.ViewOffset.Y + mItemAreaBounds.Height) / (float)mItemSizeWithMargin.Height) * mCols - 1; } if (mFirstVisible < 0) mFirstVisible = 0; if (mFirstVisible > mImageListView.Items.Count - 1) mFirstVisible = mImageListView.Items.Count - 1; if (mLastVisible < 0) mLastVisible = 0; if (mLastVisible > mImageListView.Items.Count - 1) mLastVisible = mImageListView.Items.Count - 1; // Cache visible items if (mFirstPartiallyVisible >= 0 && mLastPartiallyVisible >= 0 && mFirstPartiallyVisible <= mImageListView.Items.Count - 1 && mLastPartiallyVisible <= mImageListView.Items.Count - 1) { for (int i = mFirstPartiallyVisible; i <= mLastPartiallyVisible; i++) cachedVisibleItems.Add(mImageListView.Items[i].Guid, false); } }