2024-09-22 11:05:41 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
namespace WPFluent.Layout;
|
|
|
|
|
|
|
2024-09-22 11:05:41 +08:00
|
|
|
|
public class WaterfallPanel : VirtualizingPanel
|
|
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static readonly DependencyProperty ColumnsProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Columns), typeof(int), typeof(WaterfallPanel), new PropertyMetadata(3));
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty SpacingProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Spacing), typeof(double), typeof(WaterfallPanel), new PropertyMetadata(5.0));
|
2024-09-22 11:05:41 +08:00
|
|
|
|
private List<double> columnHeights = [];
|
2025-02-10 20:53:40 +08:00
|
|
|
|
|
2024-09-22 11:05:41 +08:00
|
|
|
|
protected override Size MeasureOverride(Size availableSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
columnHeights.Clear();
|
|
|
|
|
|
var panelDesiredSize = new Size(0, 0);
|
|
|
|
|
|
columnHeights = new double[Columns].ToList();
|
|
|
|
|
|
double currentX = 0;
|
|
|
|
|
|
var width = availableSize.Width / Columns - (Columns * Spacing);
|
2025-02-10 20:53:40 +08:00
|
|
|
|
for(var i = 0; i < InternalChildren.Count; i++)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
if(InternalChildren[i] is not FrameworkElement child)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
child.Measure(availableSize);
|
|
|
|
|
|
child.Width = width;
|
|
|
|
|
|
var columnIndex = i % Columns;
|
|
|
|
|
|
var x = columnIndex != 0 ? currentX + Spacing : 0;
|
|
|
|
|
|
var y = columnHeights[columnIndex];
|
2025-02-10 20:53:40 +08:00
|
|
|
|
if(i >= Columns)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
y = y + Spacing;
|
|
|
|
|
|
var size = new Size(width, child.DesiredSize.Height);
|
|
|
|
|
|
child.Arrange(new Rect(new Point(x, y), size));
|
|
|
|
|
|
panelDesiredSize.Width = Math.Max(panelDesiredSize.Width, x + child.DesiredSize.Width);
|
|
|
|
|
|
panelDesiredSize.Height = Math.Max(panelDesiredSize.Height, y + child.DesiredSize.Height);
|
|
|
|
|
|
currentX = x + size.Width;
|
2025-02-10 20:53:40 +08:00
|
|
|
|
if(currentX >= Width)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
currentX = 0;
|
|
|
|
|
|
columnHeights[columnIndex] += child.DesiredSize.Height + (i >= Columns ? Spacing : 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
return panelDesiredSize;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public void AddChild(UIElement element) { Children.Add(element); }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public int Columns { get { return (int)GetValue(ColumnsProperty); } set { SetValue(ColumnsProperty, value); } }
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
public double Spacing
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (double)GetValue(SpacingProperty); }
|
|
|
|
|
|
set { SetValue(SpacingProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|