public interface IDesiredPanel
{
Size GetDesiredSize(int availableWidth, int avaiableHeight);
}
public class StackPanel : Panel, IDesiredPanel
{
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
List<Control> visibleCtrls = GetVisiableControls();
int renderHeight = 0;
for (int i = 0; i < visibleCtrls.Count; i++)
{
Control childCtrl = visibleCtrls[i];
IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
Size childDesignSize = idesiredPnl == null
? new Size(childCtrl.Width, childCtrl.Height)
: idesiredPnl.GetDesiredSize(this.Width, this.Height);
childCtrl.Location = new Point(0, renderHeight);
childCtrl.Width = childDesignSize.Width;
renderHeight += childDesignSize.Height;
}
if (this.Parent is IDesiredPanel)
{
if (visibleCtrls.Count > 0)
{
this.Height = renderHeight;
}
else
{
this.Height = 3;
}
}
else if (this.DesignMode == false)
{
this.Height = renderHeight;
}
}
private List<Control> GetVisiableControls()
{
List<Control> controls = new List<Control>();
foreach (Control c in this.Controls)
{
if (c.Visible)
{
controls.Add(c);
}
}
controls.Reverse();
return controls;
}
public Size GetDesiredSize(int availableWidth, int avaiableHeight)
{
List<Control> visibleCtrls = GetVisiableControls();
int desiredHeight = 0;
for (int i = 0; i < visibleCtrls.Count; i++)
{
Control childCtrl = visibleCtrls[i];
IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
Size childDesiredSize = idesiredPnl == null
? new Size(childCtrl.Width, childCtrl.Height)
: idesiredPnl.GetDesiredSize(availableWidth, avaiableHeight);
desiredHeight += childDesiredSize.Height;
}
return new Size(availableWidth, desiredHeight);
}
}
public class WrapPanel : Panel, IDesiredPanel
{
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
List<Control> visibleCtrls = GetVisiableControls();
int renderHeight = 0;
int curLineWidth = 0, curLineMaxHeight = 0;
for (int i = 0; i < visibleCtrls.Count; i++)
{
Control childCtrl = visibleCtrls[i];
IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
Size childDesignSize = idesiredPnl == null
? new Size(childCtrl.Width, childCtrl.Height)
: idesiredPnl.GetDesiredSize(this.Width, this.Height);
childCtrl.Width = childDesignSize.Width;
childCtrl.Height = childDesignSize.Height;
if (curLineWidth == 0)
{ //第一个元素
curLineMaxHeight = Math.Max(curLineMaxHeight, childDesignSize.Height);
childCtrl.Location = new Point(0, renderHeight);
curLineWidth += childDesignSize.Width;
}
else if (curLineWidth + childDesignSize.Width < this.Width)
{ //非第一个元素,再次元素则宽度累加 不会超出
childCtrl.Location = new Point(curLineWidth, renderHeight);
curLineWidth += childDesignSize.Width;
}
else
{ //非第一个元素,再次元素则宽度累加 会超出,采用换行
renderHeight += curLineMaxHeight;
//换行了
childCtrl.Location = new Point(0, renderHeight);
curLineWidth = childCtrl.Width;
curLineMaxHeight = childCtrl.Height;
}
if (curLineWidth > this.Width)
{ //这个元素溢出了
renderHeight += curLineMaxHeight; //累加上
curLineWidth = 0; //重置为0
curLineMaxHeight = 0; //需要换到下一行
}
}
if (curLineWidth > 0)
{
renderHeight += curLineMaxHeight;
}
if(this.Parent is IDesiredPanel)
{
if(visibleCtrls.Count>0)
{
this.Height = renderHeight;
}
else
{
this.Height = 3;
}
}
else if (this.DesignMode == false)
{
this.Height = renderHeight;
}
}
private List<Control> GetVisiableControls()
{
List<Control> controls = new List<Control>();
foreach (Control c in this.Controls)
{
if (c.Visible)
{
controls.Add(c);
}
}
controls.Reverse();
return controls;
}
public Size GetDesiredSize(int availableWidth,int avaiableHeight)
{
List<Control> visibleCtrls = GetVisiableControls();
int desiredHeight = 0;
int curLineWidth = 0,curLineMaxHeight = 0;
for (int i = 0; i < visibleCtrls.Count; i++)
{
Control childCtrl = visibleCtrls[i];
IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
Size childDesiredSize = idesiredPnl == null
? new Size(childCtrl.Width, childCtrl.Height)
: idesiredPnl.GetDesiredSize(availableWidth,avaiableHeight);
if (curLineWidth == 0)
{
curLineMaxHeight = Math.Max(curLineMaxHeight, childDesiredSize.Height);
curLineWidth += childDesiredSize.Width;
}
else if (curLineWidth + childDesiredSize.Width < availableWidth)
{
curLineWidth += childDesiredSize.Width;
}
else
{
desiredHeight += curLineMaxHeight;
curLineWidth = childCtrl.Width;
curLineMaxHeight = childCtrl.Height;
}
if (curLineWidth > availableWidth)
{
desiredHeight += curLineMaxHeight;
curLineWidth = 0;
curLineMaxHeight = 0;
}
}
if (curLineWidth > 0)
{
desiredHeight += curLineMaxHeight;
}
return new Size(availableWidth, desiredHeight);
}
}
标签:StackPanel,Height,Width,int,curLineMaxHeight,curLineWidth,WPF,childCtrl,WinForm
From: https://www.cnblogs.com/wandia/p/18499674