System.Windows.Controls.VirtualizingStackPanel.MeasureOverride C# (CSharp) Method

MeasureOverride() protected method

protected MeasureOverride ( Size availableSize ) : Size
availableSize Size
return Size
		protected override Size MeasureOverride (Size availableSize)
		{
			ItemsControl owner = ItemsControl.GetItemsOwner (this);
			Size measured = new Size (0, 0);
			bool invalidate = false;
			int nvisible = 0;
			int beyond = 0;
			int index;
			
			if (Orientation == Orientation.Horizontal)
				index = (int) HorizontalOffset;
			else
				index = (int) VerticalOffset;

			// Ensure we always touch ItemContainerGenerator as by accessing this property
			// we hook up to some events on it.
			IItemContainerGenerator generator = ItemContainerGenerator;
			if (owner.Items.Count > 0) {
				GeneratorPosition start;
				Size childAvailable;
				int insertAt;
				
				// Calculate the child sizing constraints
				childAvailable = availableSize;
				if (Orientation == Orientation.Vertical) {
					childAvailable.Height = double.PositiveInfinity;
					if (CanHorizontallyScroll)
						childAvailable.Width = double.PositiveInfinity;
				} else {
					childAvailable.Width = double.PositiveInfinity;
					if (CanVerticallyScroll)
						childAvailable.Height = double.PositiveInfinity;
				}
				
				// Next, prepare and measure the extents of our viewable items...
				start = generator.GeneratorPositionFromIndex (index);
				insertAt = (start.Offset == 0) ? start.Index : start.Index + 1;
				
				using (generator.StartAt (start, GeneratorDirection.Forward, true)) {
					bool isNewlyRealized;
					
					for (int i = index; i < owner.Items.Count && beyond < 2; i++, insertAt++) {
						// Generate the child container
						UIElement child = (UIElement) generator.GenerateNext (out isNewlyRealized);
						if (isNewlyRealized || insertAt >= Children.Count || Children[insertAt] != child) {
							// Add newly created children to the panel
							if (insertAt < Children.Count) {
								InsertInternalChild (insertAt, child);
							} else {
								AddInternalChild (child);
							}
							
							generator.PrepareItemContainer (child);
						}
						
						// Call Measure() on the child to both force layout and also so
						// that we can figure out when to stop adding children (e.g. when
						// we go beyond the viewable area)
						child.Measure (childAvailable);
						Size size = child.DesiredSize;
						nvisible++;
						
						if (Orientation == Orientation.Vertical) {
							measured.Width = Math.Max (measured.Width, size.Width);
							measured.Height += size.Height;
							
							if (measured.Height > availableSize.Height)
								beyond++;
						} else {
							measured.Height = Math.Max (measured.Height, size.Height);
							measured.Width += size.Width;
							
							if (measured.Width > availableSize.Width)
								beyond++;
						}
					}
				}
			}
			
			// FIXME: this if-check is a workaround for a bug
			// exposed by NBC Olympics but should not normally be
			// here.
			if (nvisible > 0)
				RemoveUnusedContainers (index, nvisible);
			
			nvisible -= beyond;
			
			// Update our Extent and Viewport values
			if (Orientation == Orientation.Vertical) {
				if (ExtentHeight != owner.Items.Count) {
					ExtentHeight = owner.Items.Count;
					invalidate = true;
				}
				
				if (ExtentWidth != measured.Width) {
					ExtentWidth = measured.Width;
					invalidate = true;
				}
				
				if (ViewportHeight != nvisible) {
					ViewportHeight = nvisible;
					invalidate = true;
				}
				
				if (ViewportWidth != availableSize.Width) {
					ViewportWidth = availableSize.Width;
					invalidate = true;
				}
				
				// Massage 'measured' into what Silverlight would return...
				measured.Width = Math.Min (measured.Width, availableSize.Width);
				if (!Double.IsPositiveInfinity (availableSize.Height))
					measured.Height = availableSize.Height;
			} else {
				if (ExtentHeight != measured.Height) {
					ExtentHeight = measured.Height;
					invalidate = true;
				}
				
				if (ExtentWidth != owner.Items.Count) {
					ExtentWidth = owner.Items.Count;
					invalidate = true;
				}
				
				if (ViewportHeight != availableSize.Height) {
					ViewportHeight = availableSize.Height;
					invalidate = true;
				}
				
				if (ViewportWidth != nvisible) {
					ViewportWidth = nvisible;
					invalidate = true;
				}
				
				// Massage 'measured' into what Silverlight would return...
				measured.Height = Math.Min (measured.Height, availableSize.Height);
				if (!Double.IsPositiveInfinity (availableSize.Width))
					measured.Width = availableSize.Width;
			}
			
			if (invalidate && ScrollOwner != null)
				ScrollOwner.InvalidateScrollInfo ();
			
			return measured;
		}