自定义布局控件


public class BreakWrapPanel : Panel
{
public static readonly DependencyProperty IsBreakForceProperty =
DependencyProperty.RegisterAttached("BreakForce", typeof(bool), typeof(BreakWrapPanel), new FrameworkPropertyMetadata { AffectsArrange = true, AffectsParentMeasure = true });//设置了这个属性值更改重新测量跟排布

[AttachedPropertyBrowsableForChildren()]
public static bool GetBreakForce(DependencyObject d)
{
return (bool)(d as UIElement).GetValue(IsBreakForceProperty);
}
public static void SetBreakForce(DependencyObject d, bool value)
{
(d as UIElement).SetValue(IsBreakForceProperty, value);
}

protected override Size MeasureOverride(Size availableSize)  //测量内容控件需要的尺寸大小
{
foreach (UIElement item in this.InternalChildren)
{
item.Measure(availableSize);
//item.DesiredSize;
}
return availableSize;
}

protected override Size ArrangeOverride(Size finalSize)//排布内容控件的位置
{
double x = 0, y = 0;
Size currentLineSize = new Size();
int firstIndexPerLine = 0;

UIElementCollection elements = this.InternalChildren;

for (int i = 0; i < elements.Count; i++)
{
Size desiredSize = elements[i].DesiredSize;

if (desiredSize.Width > finalSize.Width)
{
elements[i].Arrange(new Rect(0, y, elements[i].DesiredSize.Width, elements[i].DesiredSize.Height));
y += desiredSize.Height;
}
else
{
if (GetBreakForce(elements[i]) || currentLineSize.Width + desiredSize.Width > finalSize.Width)
{
ElementArrange(firstIndexPerLine, i + 1, y, currentLineSize.Height);
y += currentLineSize.Height;
currentLineSize = desiredSize;

firstIndexPerLine = i;
}
else
{
currentLineSize.Width += desiredSize.Width;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
}
if (firstIndexPerLine < elements.Count)
{
ElementArrange(firstIndexPerLine, elements.Count, y, currentLineSize.Height);
}
}
return finalSize;
}

private void ElementArrange(int startIndex, int endIndex, double y, double lineHeight)
{
double x = 0;
UIElementCollection elements = this.InternalChildren;

for (int i = startIndex; i < endIndex; i++)
{
elements[i].Arrange(new Rect(x, y, elements[i].DesiredSize.Width, lineHeight));
x += elements[i].DesiredSize.Width;
}
}
}

WPF