/// <summary> /// Draws the content of a <see cref="T:System.Windows.Media.DrawingContext" /> object during the render pass of a <see cref="T:System.Windows.Controls.Panel" /> element. /// </summary> /// <param name="dc">The <see cref="T:System.Windows.Media.DrawingContext" /> object to draw.</param> protected override void OnRender(DrawingContext dc) { base.OnRender(dc); if (!ShowGroupHeaders || GroupHeaderRenderer == null) { return; } var offsetTop = 0d; if (_scrollVertical.Visibility == Visibility.Visible) { offsetTop = _scrollVertical.Value * -1; } var currentTop = offsetTop + Padding.Top; var currentGroupIsExpanded = true; foreach (var control in _lastControls) { var lineHeight = 0d; if (control.Label != null) { lineHeight = control.Label.DesiredSize.Height; } if (control.Edit != null) { lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height); } lineHeight = SnapToPixel(lineHeight); if (control.Label != null && SimpleView.GetGroupBreak(control.Label)) { var groupTitle = SimpleView.GetGroupTitle(control.Label); if (_renderedGroups.ContainsKey(groupTitle)) { currentGroupIsExpanded = _renderedGroups[groupTitle].IsExpanded; var group = _renderedGroups[groupTitle]; var width = ActualWidth - Padding.Left - Padding.Right; if (_scrollVertical.Visibility == Visibility.Visible) { width -= SystemParameters.VerticalScrollBarWidth; } dc.PushTransform(new TranslateTransform(Padding.Left, currentTop)); GroupHeaderRenderer.RenderHeader(dc, currentTop, width, groupTitle, group.IsExpanded); dc.Pop(); group.LastRenderTopPosition = currentTop; currentTop += _renderedGroups[groupTitle].Height; } } if (currentGroupIsExpanded) { currentTop += lineHeight + VerticalElementSpacing; } } }
/// <summary> /// Invoked when an unhandled MouseDown attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event. /// </summary> /// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs" /> that contains the event data. This event data reports details about the mouse button that was pressed and the handled state.</param> protected override void OnMouseDown(MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && e.ClickCount == 1) { foreach (var control in _lastControls) { if (control.Label != null && SimpleView.GetGroupBreak(control.Label)) { var groupTitle = SimpleView.GetGroupTitle(control.Label); if (_renderedGroups.ContainsKey(groupTitle)) { var group = _renderedGroups[groupTitle]; var y = group.LastRenderTopPosition; var positionY = e.GetPosition(this).Y; if (positionY >= y && positionY <= y + group.Height) { e.Handled = true; group.IsExpanded = !group.IsExpanded; InvalidateMeasure(); InvalidateArrange(); InvalidateVisual(); return; } } } } } base.OnMouseDown(e); }
/// <summary> /// Arranges the content of a <see cref="T:System.Windows.Controls.StackPanel"/> element. /// </summary> /// <param name="arrangeSize">The <see cref="T:System.Windows.Size"/> that this element should use to arrange its child elements.</param> /// <returns> /// The <see cref="T:System.Windows.Size"/> that represents the arranged size of this <see cref="T:System.Windows.Controls.StackPanel"/> element and its child elements. /// </returns> protected override Size ArrangeOverride(Size arrangeSize) { var top = 0d; var left = 0d; var bottom = 0d; var right = 0d; var usableWidth = _calculatedContentWidth; var usableHeight = _calculatedContentHeight; if (Orientation == Orientation.Vertical) { usableWidth = Math.Max(usableWidth, arrangeSize.Width); } else { usableHeight = Math.Max(usableHeight, arrangeSize.Height); } var extraMargin = ChildItemMargin; var topElements = new List <FrameworkElement>(); var bottomElements = new List <FrameworkElement>(); if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible) { top = _scrollVertical.Value * -1; usableWidth -= _scrollVertical.ActualWidth + 2; } else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible) { left = _scrollHorizontal.Value * -1; usableHeight -= _scrollHorizontal.ActualHeight + 2; } var contentSize = GeometryHelper.NewSize(usableWidth, usableHeight); var topOrigin = top; var leftOrigin = left; foreach (var element2 in Children.OfType <FrameworkElement>().Where(e => e.Visibility != Visibility.Collapsed)) { if (Orientation == Orientation.Vertical) { if (element2.VerticalAlignment != VerticalAlignment.Bottom) { topElements.Add(element2); } else { bottomElements.Add(element2); } } else if (element2.HorizontalAlignment != HorizontalAlignment.Right) { topElements.Add(element2); } else { bottomElements.Add(element2); } } // Calculating the height of the bottom items foreach (var element in bottomElements) { if (Orientation == Orientation.Vertical) { var extraBottom = extraMargin.Bottom; if (element is TextBlock || element is Label) { if (IgnoreChildItemBottomMarginForTextElements) { extraBottom = 0; } } bottom += element.DesiredSize.Height + extraMargin.Top + extraBottom; if (SimpleView.GetGroupBreak(element)) { bottom += GroupSpacing; } } else { right += element.DesiredSize.Width; if (SimpleView.GetGroupBreak(element)) { right += GroupSpacing; } } } var topCounter = 0; foreach (var element2 in topElements) { topCounter++; var extraBottom = extraMargin.Bottom; if (element2 is TextBlock || element2 is Label) { if (IgnoreChildItemBottomMarginForTextElements) { extraBottom = 0; } } var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom); if (Orientation == Orientation.Vertical) { // Top Alignment if (topCounter < topElements.Count || !LastTopItemFillsSpace) { if (SimpleView.GetGroupBreak(element2)) { top += GroupSpacing; } element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right, element2.DesiredSize.Height)); top += desiredSize.Height; } else { var elementAutoSizeHeight = Math.Max(0, usableHeight + topOrigin - top - bottom - extraMargin.Top - extraMargin.Bottom - LastTopItemFillMargin); element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right - extraMargin.Left, elementAutoSizeHeight)); top += elementAutoSizeHeight; } } else { // Left Alignment if (topCounter < topElements.Count || !LastTopItemFillsSpace) { if (SimpleView.GetGroupBreak(element2)) { left += GroupSpacing; } element2.Arrange(GeometryHelper.NewRect(left + extraMargin.Left, extraMargin.Top, element2.DesiredSize.Width, contentSize.Height - extraBottom)); left += desiredSize.Width; } else { var elementAutoSizeWidth = Math.Max(0, usableWidth + leftOrigin - left - right - extraMargin.Left - extraMargin.Right - LastTopItemFillMargin); element2.Arrange(GeometryHelper.NewRect(left + extraMargin.Left, extraMargin.Top, elementAutoSizeWidth, contentSize.Height - extraBottom - extraMargin.Top)); left += elementAutoSizeWidth; } } } // Second pass to arrange the elements on the "other side" var availableHeight = contentSize.Height; var availableWidth = contentSize.Width; var top2 = topOrigin + availableHeight - bottom - extraMargin.Top; if (top2 < top) { top2 = top; // Can't overlap the items that are already there } var left2 = leftOrigin + availableWidth - right; if (left2 < left) { left2 = left; // Can't overlap the items that are already there } foreach (var element2 in bottomElements) { var extraBottom = extraMargin.Bottom; if (element2 is TextBlock || element2 is Label) { if (IgnoreChildItemBottomMarginForTextElements) { extraBottom = 0; } } var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom); if (Orientation == Orientation.Vertical) { if (SimpleView.GetGroupBreak(element2)) { top2 += GroupSpacing; } element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top2 + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right, element2.DesiredSize.Height)); top2 += desiredSize.Height; } else { if (SimpleView.GetGroupBreak(element2)) { left2 += GroupSpacing; } element2.Arrange(GeometryHelper.NewRect(left2 + extraMargin.Left, extraMargin.Top, element2.DesiredSize.Width, contentSize.Height - extraMargin.Top - extraBottom)); left2 += desiredSize.Width; } } return(arrangeSize); }
/// <summary> /// Measures the child elements of a <see cref="T:System.Windows.Controls.StackPanel"/> in anticipation of arranging them during the <see cref="M:System.Windows.Controls.StackPanel.ArrangeOverride(System.Windows.Size)"/> pass. /// </summary> /// <param name="constraint">An upper limit <see cref="T:System.Windows.Size"/> that should not be exceeded.</param> /// <returns> /// The <see cref="T:System.Windows.Size"/> that represents the desired size of the element. /// </returns> protected override Size MeasureOverride(Size constraint) { var topUsed = 0d; var bottomUsed = 0d; var leftUsed = 0d; var rightUsed = 0d; var extraMargin = ChildItemMargin; var topElements = new List <FrameworkElement>(); var bottomElements = new List <FrameworkElement>(); if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible) { constraint.Width = Math.Max(constraint.Width - _scrollVertical.ActualWidth, 0d); } else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible) { constraint.Height = Math.Max(constraint.Height - _scrollHorizontal.ActualHeight, 0d); } foreach (var element2 in Children.OfType <FrameworkElement>().Where(e => e.Visibility != Visibility.Collapsed)) { if (Orientation == Orientation.Vertical) { if (element2.VerticalAlignment != VerticalAlignment.Bottom) { topElements.Add(element2); } else { bottomElements.Add(element2); } } else if (element2.HorizontalAlignment != HorizontalAlignment.Right) { topElements.Add(element2); } else { bottomElements.Add(element2); } } // starting with the bottom elements foreach (var element2 in bottomElements) { if (Orientation == Orientation.Vertical) { element2.Measure(new Size(constraint.Width, double.PositiveInfinity)); } else { element2.Measure(new Size(double.PositiveInfinity, constraint.Height)); } var extraBottom = extraMargin.Bottom; if (element2 is TextBlock || element2 is Label) { if (IgnoreChildItemBottomMarginForTextElements) { extraBottom = 0; } } var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom); if (Orientation == Orientation.Vertical) { bottomUsed += desiredSize.Height; leftUsed = Math.Max(leftUsed, desiredSize.Width); } else { rightUsed += desiredSize.Width; topUsed = Math.Max(topUsed, desiredSize.Height); } } // now for the top elements var topCounter = 0; foreach (var element2 in topElements) { topCounter++; var constraint2 = constraint; var extraBottom = extraMargin.Bottom; if (topCounter == topElements.Count && LastTopItemFillsSpace) { if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Height) && constraint.Height > 0) { constraint2 = GeometryHelper.NewSize(constraint.Width, Math.Max(element2.MinHeight, constraint.Height - topUsed - bottomUsed - LastTopItemFillMargin - extraMargin.Top - extraBottom)); extraBottom = LastTopItemFillMargin; } else if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Width) && constraint.Width > 0) { constraint2 = GeometryHelper.NewSize(Math.Max(element2.MinWidth, constraint.Width - leftUsed - rightUsed - LastTopItemFillMargin), constraint.Height); extraBottom = LastTopItemFillMargin; } } else { if (Orientation == Orientation.Vertical) { constraint2 = new Size(constraint2.Width, double.PositiveInfinity); } else { constraint2 = new Size(double.PositiveInfinity, constraint2.Height); } } element2.Measure(constraint2); if (element2 is TextBlock || element2 is Label) { if (IgnoreChildItemBottomMarginForTextElements) { extraBottom = 0; } } var desiredSize = GeometryHelper.NewSize(Math.Max(0, element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right), Math.Max(0, element2.DesiredSize.Height + extraMargin.Top + extraBottom)); if (Orientation == Orientation.Vertical) { topUsed += desiredSize.Height; leftUsed = Math.Max(leftUsed, desiredSize.Width); if (SimpleView.GetGroupBreak(element2)) { leftUsed += GroupSpacing; } } else { leftUsed += desiredSize.Width; topUsed = Math.Max(topUsed, desiredSize.Height); if (SimpleView.GetGroupBreak(element2)) { topUsed += GroupSpacing; } } } var widthUsed = leftUsed + rightUsed; var heightUsed = topUsed + bottomUsed; if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Width) && constraint.Width > 0) { widthUsed = Math.Min(constraint.Width, widthUsed); // In vertical orientation, we use no more than the width available to us } if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Width) && constraint.Width > 0 && widthUsed < constraint.Width) { widthUsed = Math.Min(constraint.Width, widthUsed); // In horizontal orientation, if we haven't used up the entire width yet, we occupy the entire available space } if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Height) && constraint.Height > 0) { heightUsed = Math.Min(constraint.Height, heightUsed); // In horizontal orientation, we use no more than the height available to us } if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Height) && constraint.Height > 0 && heightUsed < constraint.Height) { heightUsed = Math.Min(constraint.Height, heightUsed); // In vertical orientation, if we haven't used up the entire height yet, we occupy the entire available space } if (Orientation == Orientation.Vertical) { _calculatedContentHeight = double.IsInfinity(constraint.Height) ? heightUsed : Math.Max(constraint.Height, heightUsed); _calculatedContentWidth = widthUsed; } else { _calculatedContentHeight = heightUsed; _calculatedContentWidth = double.IsInfinity(constraint.Width) ? widthUsed : Math.Max(constraint.Width, widthUsed); } var finalSize = GeometryHelper.NewSize(widthUsed, heightUsed); // Checking if this forces us to change scroll bar visibility and thus invalidate everything if (Orientation == Orientation.Vertical) { if (heightUsed > constraint.Height) { if (_scrollVertical.Visibility != Visibility.Visible && ScrollBarMode == BidirectionalStackPanelScrollBarModes.Automatic) { _scrollVertical.Visibility = Visibility.Visible; InvalidateAllVisuals(this); // Triggers recalculation of everything with a visible scroll bar } _scrollVertical.Maximum = _calculatedContentHeight - constraint.Height; _scrollVertical.ViewportSize = constraint.Height; _scrollVertical.LargeChange = constraint.Height; finalSize.Height = constraint.Height; } else if (heightUsed <= constraint.Height && _scrollVertical.Visibility != Visibility.Collapsed) { _scrollVertical.Visibility = Visibility.Collapsed; InvalidateAllVisuals(this); } } else { if (widthUsed > constraint.Width) { if (_scrollHorizontal.Visibility != Visibility.Visible && ScrollBarMode == BidirectionalStackPanelScrollBarModes.Automatic) { _scrollHorizontal.Visibility = Visibility.Visible; InvalidateAllVisuals(this); // Triggers recalculation of everything with a visible scroll bar } _scrollHorizontal.Maximum = _calculatedContentWidth - constraint.Width; _scrollHorizontal.LargeChange = constraint.Width; _scrollHorizontal.ViewportSize = constraint.Width; finalSize.Width = constraint.Width; } else if (widthUsed <= constraint.Width && _scrollHorizontal.Visibility != Visibility.Collapsed) { _scrollHorizontal.Visibility = Visibility.Collapsed; InvalidateAllVisuals(this); } } if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible) { finalSize.Width += _scrollVertical.ActualWidth; } else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible) { finalSize.Height += _scrollHorizontal.ActualHeight; } return(finalSize); }
/// <summary> /// When overridden in a derived class, positions child elements and determines a size for a <see cref="T:System.Windows.FrameworkElement" /> derived class. /// </summary> /// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param> /// <returns>The actual size used.</returns> protected override Size ArrangeOverride(Size finalSize) { var finalSizeInternal = finalSize; if (Padding.Top > 0 || Padding.Bottom > 0 || Padding.Right > 0 || Padding.Left > 0) { var availableHeight = finalSize.Height - Padding.Top - Padding.Bottom; if (availableHeight < 0d) { availableHeight = 0d; } var availableWidth = finalSize.Width - Padding.Left - Padding.Right; if (availableWidth < 0d) { availableWidth = 0d; } finalSizeInternal = GeometryHelper.NewSize(availableWidth, availableHeight); } if (_lastControls == null) { return(base.ArrangeOverride(finalSize)); } var finalWidth = finalSizeInternal.Width; if (_scrollVertical.Visibility == Visibility.Visible) { finalWidth = Math.Max(finalWidth - SystemParameters.VerticalScrollBarWidth, 1); } var offsetTop = 0d; if (_scrollVertical.Visibility == Visibility.Visible) { offsetTop = _scrollVertical.Value * -1; } var currentTop = offsetTop + Padding.Top; if (!ShowGroupHeaders || GroupHeaderRenderer == null) { foreach (var control in _lastControls) { var lineHeight = 0d; if (control.Label != null) { lineHeight = control.Label.DesiredSize.Height; } if (control.Edit != null) { lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height); } lineHeight = SnapToPixel(lineHeight); if (control.Label != null) { if (!control.LabelSpansFullWidth) { control.Label.Arrange(GeometryHelper.NewRect(Padding.Left, currentTop, _labelWidth, lineHeight)); } else { control.Label.Arrange(GeometryHelper.NewRect(Padding.Left, currentTop, SnapToPixel(finalWidth), lineHeight)); } } if (control.Edit != null && !control.LabelSpansFullWidth) { var editLeft = SnapToPixel(_labelWidth + HorizontalElementSpacing + Padding.Left); var editWidth = Math.Max(SnapToPixel(finalWidth - editLeft + Padding.Left), 0); for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--) { var flowControl = control.AdditionalEditControls[flowControlCounter]; var flowWidth = Math.Min(flowControl.DesiredSize.Width, editWidth); flowControl.Arrange(GeometryHelper.NewRect(editLeft + editWidth - flowWidth, currentTop, flowWidth, lineHeight)); editWidth -= (flowWidth + AdditionalFlowElementSpacing); if (editWidth < 0.1) { editWidth = 0d; } } control.Edit.Arrange(GeometryHelper.NewRect(editLeft, currentTop, editWidth, lineHeight)); } currentTop += lineHeight + VerticalElementSpacing; } } else { var itemIndent = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering("X").Left; var currentGroupIsExpanded = true; foreach (var control in _lastControls) { var lineHeight = 0d; if (control.Label != null) { lineHeight = control.Label.DesiredSize.Height; } if (control.Edit != null) { lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height); } lineHeight = SnapToPixel(lineHeight); if (control.Label != null && SimpleView.GetGroupBreak(control.Label)) { var groupTitle = SimpleView.GetGroupTitle(control.Label); if (_renderedGroups.ContainsKey(groupTitle)) { currentGroupIsExpanded = _renderedGroups[groupTitle].IsExpanded; currentTop += _renderedGroups[groupTitle].Height; } } if (currentGroupIsExpanded) { if (control.Label != null) { control.Label.Visibility = Visibility.Visible; if (!control.LabelSpansFullWidth) { control.Label.Arrange(GeometryHelper.NewRect(Padding.Left + itemIndent, currentTop, _labelWidth, lineHeight)); } else { control.Label.Arrange(GeometryHelper.NewRect(Padding.Left + itemIndent, currentTop, SnapToPixel(finalWidth - itemIndent), lineHeight)); } } if (control.Edit != null) { control.Edit.Visibility = Visibility.Visible; var editLeft = SnapToPixel(_labelWidth + HorizontalElementSpacing + Padding.Left + itemIndent); var editWidth = Math.Max(SnapToPixel(finalWidth - editLeft + Padding.Left), 0); for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--) { var flowControl = control.AdditionalEditControls[flowControlCounter]; var flowWidth = Math.Min(flowControl.DesiredSize.Width, editWidth); flowControl.Visibility = Visibility.Visible; flowControl.Arrange(GeometryHelper.NewRect(editLeft + editWidth - flowWidth, currentTop, flowWidth, lineHeight)); editWidth -= (flowWidth + AdditionalFlowElementSpacing); if (editWidth < 0.1) { editWidth = 0d; } } control.Edit.Arrange(GeometryHelper.NewRect(editLeft, currentTop, editWidth, lineHeight)); } currentTop += lineHeight + VerticalElementSpacing; } else { if (control.Label != null) { control.Label.Visibility = Visibility.Collapsed; } if (control.Edit != null) { control.Edit.Visibility = Visibility.Collapsed; } foreach (var flowControl in control.AdditionalEditControls) { flowControl.Visibility = Visibility.Collapsed; } } } } return(base.ArrangeOverride(finalSize)); }
/// <summary> /// When overridden in a derived class, measures the size in layout required for child elements and determines a size for the <see cref="T:System.Windows.FrameworkElement" />-derived class. /// </summary> /// <param name="availableSize">The available size that this element can give to child elements. Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param> /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns> protected override Size MeasureOverride(Size availableSize) { var availableSizeInternal = availableSize; if (Padding.Top > 0 || Padding.Bottom > 0 || Padding.Right > 0 || Padding.Left > 0) { var availableHeight = availableSize.Height - Padding.Top - Padding.Bottom; if (availableHeight < 0d) { availableHeight = 0d; } var availableWidth = availableSize.Width - Padding.Left - Padding.Right; if (availableWidth < 0d) { availableWidth = 0d; } availableSizeInternal = GeometryHelper.NewSize(availableWidth, availableHeight); } _lastControls = GetControls(); InvalidateVisual(); var widestLabel = 0d; var totalHeight = 0d; var foundGroupHeader = false; var groupPadding = new Thickness(); if (ShowGroupHeaders && GroupHeaderRenderer != null) { foundGroupHeader = _lastControls.Where(c => c.Label != null).Any(control => !string.IsNullOrEmpty(SimpleView.GetGroupTitle(control.Label))); } if (foundGroupHeader) { groupPadding = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering("X"); availableSizeInternal = GeometryHelper.NewSize(Math.Max(availableSizeInternal.Width - groupPadding.Left, 0), Math.Max(availableSizeInternal.Height, 0)); } foreach (var control in _lastControls.Where(c => c.Label != null)) { control.Label.Measure(availableSizeInternal); if (!control.LabelSpansFullWidth) // For widest-label measurements, we do not consider span labels, since they always use the full width { widestLabel = Math.Max(control.Label.DesiredSize.Width, widestLabel); } } foreach (var control in _lastControls.Where(c => !c.LabelSpansFullWidth && c.Edit != null)) { var currentMaxWidth = SnapToPixel(availableSizeInternal.Width - widestLabel - HorizontalElementSpacing - groupPadding.Left); for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--) { var flowControl = control.AdditionalEditControls[flowControlCounter]; var availableEditSize = GeometryHelper.NewSize(currentMaxWidth, availableSize.Height); flowControl.Measure(availableEditSize); currentMaxWidth = Math.Max(SnapToPixel(currentMaxWidth - flowControl.DesiredSize.Width), 0); } control.Edit.Measure(GeometryHelper.NewSize(currentMaxWidth, availableSize.Height)); } var currentGroupIsExpanded = true; foreach (var control in _lastControls) { var itemHeight = 0d; if (control.Label != null) { itemHeight = control.Label.DesiredSize.Height; } if (control.Edit != null && !control.LabelSpansFullWidth) { itemHeight = Math.Max(itemHeight, control.Edit.DesiredSize.Height); foreach (var flowControl in control.AdditionalEditControls) { itemHeight = Math.Max(itemHeight, flowControl.DesiredSize.Height); } } itemHeight = SnapToPixel(itemHeight); if (ShowGroupHeaders && control.Label != null && GroupHeaderRenderer != null && SimpleView.GetGroupBreak(control.Label)) { var groupHeader = SimpleView.GetGroupTitle(control.Label) ?? string.Empty; if (!_renderedGroups.ContainsKey(groupHeader)) { _renderedGroups.Add(groupHeader, new PropertySheetGroupHeaderInfo { IsExpanded = true }); } currentGroupIsExpanded = _renderedGroups[groupHeader].IsExpanded; var currentPadding = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering(string.IsNullOrEmpty(groupHeader) ? "X" : groupHeader); _renderedGroups[groupHeader].Height = currentPadding.Top; totalHeight += SnapToPixel(currentPadding.Top); } if (currentGroupIsExpanded) { totalHeight += itemHeight + VerticalElementSpacing; } } _labelWidth = widestLabel; totalHeight += Padding.Top + Padding.Bottom; _lastTotalHeight = totalHeight; HandleScrollBarVisibility(totalHeight, availableSize); if (_scrollVertical.Visibility == Visibility.Visible) { foreach (var control in _lastControls.Where(c => !c.LabelSpansFullWidth && c.Edit != null)) { var currentMaxWidth = SnapToPixel(SnapToPixel(availableSizeInternal.Width - widestLabel - HorizontalElementSpacing - SystemParameters.VerticalScrollBarWidth - 1)); for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--) { var flowControl = control.AdditionalEditControls[flowControlCounter]; var availableEditSize = GeometryHelper.NewSize(currentMaxWidth, availableSize.Height); flowControl.Measure(availableEditSize); currentMaxWidth = Math.Max(SnapToPixel(currentMaxWidth - flowControl.DesiredSize.Width), 0); } control.Edit.Measure(GeometryHelper.NewSize(currentMaxWidth, availableSize.Height)); } } return(GeometryHelper.NewSize(availableSize.Width, Math.Min(totalHeight, availableSize.Height))); }