Advertisement
bobmarley12345

WPF uniform grid with spacing

Nov 27th, 2023
780
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.88 KB | None | 0 0
  1. using System.Windows;
  2. using System.Windows.Controls;
  3.  
  4. namespace FramePFX.WPF {
  5.     public class SpacedUniformGrid : Panel {
  6.         public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(SpacedUniformGrid), new PropertyMetadata(Orientation.Horizontal));
  7.         public static readonly DependencyProperty SpacingProperty = DependencyProperty.Register("Spacing", typeof(double), typeof(SpacedUniformGrid), new PropertyMetadata(0.0d));
  8.  
  9.         public Orientation Orientation {
  10.             get => (Orientation) this.GetValue(OrientationProperty);
  11.             set => this.SetValue(OrientationProperty, value);
  12.         }
  13.  
  14.         public double Spacing {
  15.             get => (double) this.GetValue(SpacingProperty);
  16.             set => this.SetValue(SpacingProperty, value);
  17.         }
  18.  
  19.         public SpacedUniformGrid() {
  20.         }
  21.  
  22.         private static double GetTotalGap(int numElements, double spacing) => numElements < 2 ? 0d : ((numElements - 1) * spacing);
  23.  
  24.         private static Size GetSlotSizePerElement(Size constraint, Orientation orientation, int numVisible, double totalGap) {
  25.             return orientation == Orientation.Horizontal ?
  26.                 new Size((constraint.Width - totalGap) / numVisible, constraint.Height) :
  27.                 new Size(constraint.Width, (constraint.Height - totalGap) / numVisible);
  28.         }
  29.  
  30.         protected override Size MeasureOverride(Size constraint) {
  31.             this.ComputeVisible(out int numVisible);
  32.             Size availableSize = GetSlotSizePerElement(constraint, this.Orientation, numVisible, GetTotalGap(numVisible, this.Spacing));
  33.             Size totalSize = new Size();
  34.             UIElementCollection children = this.InternalChildren;
  35.             for (int i = 0, count = children.Count; i < count; i++) {
  36.                 UIElement child = children[i];
  37.                 child.Measure(availableSize);
  38.                 Size desiredSize = child.DesiredSize;
  39.                 if (totalSize.Width < desiredSize.Width)
  40.                     totalSize.Width = desiredSize.Width;
  41.                 if (totalSize.Height < desiredSize.Height)
  42.                     totalSize.Height = desiredSize.Height;
  43.             }
  44.  
  45.             return totalSize;
  46.         }
  47.  
  48.         protected override Size ArrangeOverride(Size arrangeSize) {
  49.             this.ComputeVisible(out int numVisible);
  50.             double spacing = this.Spacing;
  51.             Orientation orientation = this.Orientation;
  52.             Rect finalRect = new Rect(new Point(), GetSlotSizePerElement(arrangeSize, orientation, numVisible, GetTotalGap(numVisible, spacing)));
  53.             UIElementCollection children = this.InternalChildren;
  54.             for (int i = 0, count = children.Count; i < count; i++) {
  55.                 // when a child is collapsed, it may glitch the rendering if this panel
  56.                 // doesn't get re-arranged for some reason when a child's visibility changes
  57.                 UIElement child = this.InternalChildren[i];
  58.                 child.Arrange(finalRect);
  59.                 if (child.Visibility != Visibility.Collapsed) {
  60.                     if (orientation == Orientation.Horizontal) {
  61.                         finalRect.X += finalRect.Width + spacing;
  62.                     }
  63.                     else {
  64.                         finalRect.Y += finalRect.Height + spacing;
  65.                     }
  66.                 }
  67.             }
  68.  
  69.             return arrangeSize;
  70.         }
  71.  
  72.         private void ComputeVisible(out int count) {
  73.             int visibleCount = 0;
  74.             UIElementCollection children = this.InternalChildren;
  75.             for (int i = 0, num = children.Count; i < num; i++) {
  76.                 if (children[i].Visibility != Visibility.Collapsed) {
  77.                     ++visibleCount;
  78.                 }
  79.             }
  80.  
  81.             count = visibleCount;
  82.         }
  83.     }
  84. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement