智慧就在于说出真理,按照自然行事,倾听自然的话。——赫拉克里特(上海网站建设)
WPF:一个估计最小大小的Canvas
Admin
2012年1月25日
题目的由来: &#160;&#160;&#160; <StackPanel> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Canvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>A</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160; </Canvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>B</Button> &#160;&#160;&#160; </StackPanel> &#160; 成果只有Button(B)才会显示出来:  &#160; 原因是默认Canvas的MeasureOverride返回一个空的Size对象(Width和Height都是0),这代表着Canvas的DesiredSize(UIElement.DesiredSize)是(0,0),申明Canvas本身并不请求任何大小恳求,若是父容器不强求子控件的大小,那么Canvas的大小会是0。若是父容器有无穷大,那么Canvas也无穷大。当然上述结论都是建树在Canvas的Width和Height都是主动(Double.NaN)的景象下的。 &#160; 那么上方Canvas中的A不显示,事实上Canvas的Width不是0,因为纵向的StackPanel不会限制子控件的Width,而Height则限制为最小值。所以此时Canvas的Height为0。 &#160; 可以经由过程在Canvas外侧加一个Border更形象的调查: &#160;&#160;&#160; <StackPanel> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Border BorderBrush="Red" BorderThickness="1" Padding="5"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Canvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>A</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </Canvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160; </Border> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>B</Button> &#160;&#160;&#160; </StackPanel> &#160; Canvas则略微露了出来(因为设置了Padding)  &#160; &#160; 我的解决规划就是创建一个小小的自定义Canvas,经由过程改写MeasureOverride来使其支撑估计自身最小大小,说白了就是在MeasureOverride中返回Canvas的最小大小,而不是默认的(0,0)大小。重视用Double.IsNaN断定Canvas的附加属性值是否是默认值。其次用Double.IsPositiveInfinity先断定MeasureOverride中的constraint参数值,再策画Canvas.Right和Canvas.Bottom所反射的Canvas最小值。 &#160; 成果: 纵向StackPanel: &#160;&#160;&#160; <StackPanel> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <loc:SizedCanvas xmlns:loc="clr-namespace:Mgen_WPF"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>A</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Top="20" Canvas.Left="40">B</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Right="20">C</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Bottom="2" Canvas.Right="2">D</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160; </loc:SizedCanvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>Mgen</Button> &#160;&#160;&#160; </StackPanel> &#160;  &#160; 横向StackPanel: &#160;&#160;&#160; <StackPanel Orientation="Horizontal"> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <loc:SizedCanvas xmlns:loc="clr-namespace:Mgen_WPF"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>A</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Top="20" Canvas.Left="40">B</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Right="20">C</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button Canvas.Bottom="2" Canvas.Right="2">D</Button> &#160;&#160;&#160;&#160;&#160;&#160;&#160; </loc:SizedCanvas> &#160;&#160;&#160;&#160;&#160;&#160;&#160; <Button>Mgen</Button> &#160;&#160;&#160; </StackPanel> &#160; &#160;  &#160; &#160; &#160; 下载代码或直接浏览: &#160; 当前版本的源代码下载 下载地址 重视:此为微软SkyDrive存档,请用浏览器直接下载,用某些下载对象可能无法下载 文件类型:.cs &#160; &#160; 代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; &#160; namespace Mgen_WPF { &#160;&#160;&#160; class SizedCanvas : Canvas &#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160; //改写FrameworkElement.MeasureOverride &#160;&#160;&#160;&#160;&#160;&#160;&#160; protected override Size MeasureOverride(Size constraint) &#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var infinite = new Size(double.PositiveInfinity, double.PositiveInfinity); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var maxSize = new Size(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (UIElement ele in InternalChildren) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (ele != null) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ele.Measure(infinite); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SetMaxSize(ref maxSize, ele, constraint); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return maxSize; &#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160; //经由过程断定Canvas的附加属性和空间的恳求大小来设置最大值 &#160;&#160;&#160;&#160;&#160;&#160;&#160; void SetMaxSize(ref Size size, UIElement ele, Size available) &#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; double left, top, right, bottom, width, height; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; left = Canvas.GetLeft(ele); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; top = Canvas.GetTop(ele); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; right = Canvas.GetRight(ele); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; bottom = Canvas.GetBottom(ele); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; width = ele.DesiredSize.Width; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; height = ele.DesiredSize.Height; &#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!Double.IsNaN(left)) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; width += left; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!Double.IsNaN(top)) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; height += top; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!Double.IsNaN(right) && !Double.IsPositiveInfinity(available.Width)) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; width = available.Width - right; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!Double.IsNaN(bottom) && !Double.IsPositiveInfinity(available.Height)) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; height = available.Height - bottom; &#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size.Width = Math.Max(size.Width, width); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size.Height = Math.Max(size.Height, height); &#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160; } } &#160; &#160; &#160; &#160; :D 作者:Mgen
出处:www.cnblogs.com/mgen
本文版权归作者和博客园共有,迎接转载,但未经作者赞成必须保存此段声明,且在文章页面明显地位给出原文连接,不然保存究查法令义务的权力。
|