一.控制項介紹 初看標題可能無法理解,我們看看什麼是自適應排列。 乍一看它有點像WrapPanel控制項,都是從左至右排列,如果一行排列不下就換行繼續排列,但是細看你就會發現不對,WrapPanel控制項行尾是不會對齊的,也就是說只要WrapPanel的子控制項的寬度不一致,每一行的末尾就會必定留下一段空白 ...
一.控制項介紹
初看標題可能無法理解,我們看看什麼是自適應排列。
乍一看它有點像WrapPanel控制項,都是從左至右排列,如果一行排列不下就換行繼續排列,但是細看你就會發現不對,WrapPanel控制項行尾是不會對齊的,也就是說只要WrapPanel的子控制項的寬度不一致,每一行的末尾就會必定留下一段空白,而這個控制項每一行末尾都是對齊的,這就讓人很疑惑了,既然每個子控制項的寬度不一樣,怎麼可能每一行的子控制項寬度都正好?
二.實現思路
首先我們要解決子控制項高度問題,不同於WrapPanel控制項取一個最高的子控制項高度作為行高度,這裡我們每一行子控制項的高度都是一樣的,如果直接測量子控制項的尺寸,我們會得到一堆高低不同的子控制項,所以在測量控制項的時候我們需要給它一個統一的高度,這樣就會得到一個高度一致,寬度各不同的子控制項。
其次我們使用測量出的尺寸從左至右排列,如果當前子控制項排列的位置超出了Panel控制項的最大寬度就換行繼續排列,此時的排列方式與WrapPanel控制項幾乎一致。最關鍵的點來了,我們需要計算出每一行的子控制項的測量出的總寬度,然後與Panel控制項的總寬度做計算,得出最終的行高度,然後再做第二次測量,得出最終的子控制項高度與寬度。
最後我們通過測量出的子控制項的寬度、高度、坐標等信息,在Panel控制項中正常排列即可達到最終效果。
三.關鍵代碼
3.1 第一次測量子控制項尺寸
child.Measure(new Size(double.PositiveInfinity, ChildMinHeight));
3.2 第二次測量子控制項尺寸
var rowWidth = row.CellList.Sum(item => item.Rect.Width); double width, height = child.DesiredSize.Height; var zoomRatio = availableSize.Width / rowWidth; var itemX = 0d; foreach (var item in row.CellList) { width = item.Rect.Width * zoomRatio; height = item.Rect.Height * zoomRatio; item.Rect = new Rect(itemX, item.Rect.Y, width, height); item.Element.Measure(item.Rect.Size); itemX += width; }
四.運行效果
4.1 正常效果
4.2 添加動畫以後的效果