【转】【WPF】WPF中MeasureOverride ArrangeOverride 的理解
1. Measure Arrange这两个方法是UIElement的方法
MeasureOverride ArrangeOverride这两个方法是FrameworkElement的方法,FrameworkElement是UIElement的子类
MeasureOverride传入父容器分配的可用空间,返回该容器根据其子元素大小计算确定的在布局过程中所需的大小。
ArrangeOverride传入父容易最终分配的控件大小,返回使用的实际大小
2. MeasureOverride 用于计算本身及其子控件的大小
ArrangeOverride用于布局本身及其子控件的位置和大小
3. WPF布局系统大概分为两步:Measure和Arrange
Measure方法自顶而下,递归调用各子控件的Measure方法,Measure方法会把该控件所需的大小控件存在desired size属性中,控件根据各子控件的desired size 属性确定自身空间大小,并返回自己的desired size
Arrange方法发生在Measure中,传入Measure方法计算到的大小,利用控件的位置设置分配子控件的位置
简单来说,这两个方法一个管大小,一个管布局,都需要调用子类的Measure和Arrage
public class DiagnolPanel:Panel { protected override Size MeasureOverride(Size availableSize) { var mySize = new Size(); foreach (UIElement child in this.InternalChildren) { child.Measure(availableSize); mySize.Width += child.DesiredSize.Width; mySize.Height += child.DesiredSize.Height; } return mySize; } protected override Size ArrangeOverride(Size finalSize) { var location = new Point(); int childNumber = 0; int middleChild = GetTheMiddleChild(this.InternalChildren.Count); foreach (UIElement child in this.InternalChildren) { if (childNumber < middleChild) { child.Arrange(new Rect(location, child.DesiredSize)); location.X += child.DesiredSize.Width; location.Y += child.DesiredSize.Height; } else { //The x location will always keep increasing, there is no need to take care of it location.X = GetXLocationAfterMiddleChild(childNumber); //If the UIElements are odd in number if (this.InternalChildren.Count % 2 != 0) { //We need to get the Y location of the child before middle location, //to have the same Y location for the child after middle child int relativeChildBeforeMiddle = middleChild - (childNumber - middleChild); location.Y = GetYLocationAfterMiddleChild(relativeChildBeforeMiddle); } else { ///TODO: Do the design for the even number of children } child.Arrange(new Rect(location, child.DesiredSize)); } childNumber++; } return finalSize; } private double GetXLocationAfterMiddleChild(int childNUmber) { double xLocation = 0; for (int i = 0; i < childNUmber; i++) { xLocation += this.InternalChildren[i].DesiredSize.Width; } return xLocation; } private double GetYLocationAfterMiddleChild(int relativeChildNumber) { UIElement correspondingChild = this.InternalChildren[relativeChildNumber - 2]; Point pointCoordinates = correspondingChild.TransformToAncestor((Visual)this.Parent).Transform(new Point(0, 0)); return pointCoordinates.Y; } private int GetTheMiddleChild(int count) { int middleChild; if (count % 2 == 0) { middleChild = count / 2; } else { middleChild = (count / 2) + 1; } return middleChild; } } }
<local:DiagnolPanel> <Button BorderBrush="Black" Background="Red" Content="0" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="1" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="2" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="3" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="4" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="5" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="6" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="7" Width="40"></Button> <Button BorderBrush="Black" Background="Red" Content="8" Width="40"></Button> </local:DiagnolPanel>
原文地址:http://www.mamicode.com/info-detail-1730861.html
https://www.codeproject.com/Articles/1034445/Understanding-MeasureOverride-and-ArrangeOverride
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义