UI前沿技术: 不局限于网格2012-02-11 MSDN Charles Petzold画布是 Windows Presentation Foundation (WPF) 和 Silverlight 中提供的若干布局选项之一,它是其中与传统布局传承最为紧密的。在使用子元素填充画布时,通过使用 Canvas.Left 和 Canvas.Top 附加属性指定坐标可以定位每个子元素。此模式与其他面板有显著区别,其他面板是基于简单的算法来布置子元素的,无需程序员指出实际位置。听到“画布”一词时,您可能会想到绘图和绘画。因此,使用 WPF 和 Silverlight 的程序员可能倾向于将画布归类为用于显示矢量图形。但是,当使用画布显示线、折线、多边形和路径元素时,这些元素本身就包含用于在画布中定位自身的坐标点。因此,不需要使用 Canvas.Left 和 Canvas.Top 附加属性。如果不需要画布提供的附加属性,那么为什么还要使用画布呢?是否有更好的方法?画布与网格这些年来,我越来越不愿意使用画布显示矢量图形,更倾向于使用单个单元格网格。单个单元格网格就像常规网格一样,只是没有定义任何行或列而已。如果网格只有一个单元格,则可以将多个元素放入该网格单元格中,无需使用网格的任何附加属性来指定行或列。最初,使用画布或单个单元格网格看上去非常类似。无论对矢量图形使用哪种布局方式,线、折线、多边形和路径元素都基于其坐标点并相对于容器的左上角确定其位置。画布与单个单元格网格的区别在于容器向布局系统的其余部分的显示方式。WPF 和 Silverlight 合并了一个双步的自上而下的布局,其中每个元素会询问其子元素的大小,然后负责相对于自身来组织其子元素。在此布局系统中,画布与单个单元格网格有很大区别:对于子元素,网格具有的维度与其父元素的维度相同。这些维度通常是有限维度,但画布始终向其子元素显示具有无限维度。网格向其父元素报告其子元素的总大小。而画布始终有一个明显的零大小,与其包含的子元素无关。假设有一组多边形元素构成某种类似于卡通的矢量图像。如果将这些多边形元素全部放入单个单元格网络,则该网格的大小将由多边形的最大横坐标和纵坐标决定。然后可以将网格视为布局系统中具有有限大小的普通元素,因为其大小正确反映了组合图像的大小。(实际上,只有图像的左上角位于坐标点 (0, 0) 并且没有负坐标时才会正确显示。)但是,如果将这些多边形全部放入画布,画布会向布局系统报告其大小为零。通常,在将一个组合矢量图像集成到应用程序时,几乎可以肯定的是您希望看到单个单元格网格的行为而不是画布的行为。那么画布是否毫无用处?完全不是。窍门在于巧妙利用画布的特性。实际上,画布不参与布局。因此,您可以在需要超越布局时使用画布,从而显示超出布局系统边界的图形以及在布局系统边界外浮动的图形。默认情况下,画布不修剪其子元素,因此,即使画布非常小,仍可以在其边界外部容纳子对象。画布更像是一个显示元素或图形的参考点,而不是一个容器。我认为画布是一种“突破框架思考”的优秀技术。尽管我将在 Silverlight 中显示代码示例,但您仍可以在 WPF 中使用这一技术。本文附带的可下载源代码是一个名为 ThinkingOutsideTheGrid 的 Visual Studio 解决方案,您可以在 charlespetzold.com/silverlight/ThinkingOutsideTheGrid 运行该实例。