上海百维科技,上海网站建设 上海软件开发公司热线电话:021-57700304  
  首 页 产品与服务 软件定制 成功案例 思源优势 技术学院 关于我们 联系我们
 
 
思源软件学院 >>> 根目录>>.NET技术>>WPF >>>WPF:一个估计最小大小的Canvas
智慧就在于说出真理,按照自然行事,倾听自然的话。——赫拉克里特(上海网站建设)

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 Sizedouble.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; foreachUIElement 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


本文版权归作者和博客园共有,迎接转载,但未经作者赞成必须保存此段声明,且在文章页面明显地位给出原文连接,不然保存究查法令义务的权力。


 


 

上海软件开发公司业务部:黄浦区重庆北路211号602室 | 上海软件开发公司技术部:松江区天云路259号| 上海软件开发公司综合部:松江区南期昌路346弄50号401室
上海软件开发 Copyright © 2005-2010 All Rights Reserved 电话:021-57616508  传真:57661889
沪ICP备05011021号