登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

学无止境

一点积累,与大家分享

 
 
 

日志

 
 

自定义面板  

2010-05-01 16:56:23|  分类: C#技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
from:http://msdn.microsoft.com/zh-cn/library/cc903936%28v=vs.95%29.aspx

Silverlight 提供几个布局容器:CanvasStackPanelGrid。如果您正在创建不能通过使用提供的容器轻松实现的复杂布局,可以创建一个自定义面板,该面板允许您定义面板子级的布局行为。若要这样做,请从 Panel 派生并重写其 MeasureOverrideArrangeOverride 方法。

本主题包括下列各节。

先决条件

在按照本主题中的步骤操作之前,应熟悉在 Silverlight 中如何调整对象大小和定位对象。有关详细信息,请参见 Silverlight 布局系统

测量

面板的布局处理过程中的第一个步骤是测量每个子级并确定面板应分配多少空间给该子级。此外,返回可用于整个面板的空间大小。

下面的示例显示为一个面板 (BlockPanel) 重写 MeasureOverride 方法的情况,该面板在 3x3 的网格中放置 9 个子级,每个单元格为 100x100。

//First measure all children and return available size of panel
protected override Size MeasureOverride(Size availableSize)
{

//Measure first 9 children giving them space up to 100x100, remaining children get 0x0
int i =0;
foreach (FrameworkElement child in Children)
{
if (i < 9)
{
child.Measure(new Size(100, 100));
}
else
{
child.Measure(new Size(0, 0));
}

i++;
}


//return the size available to the whole panel, which is 300x300
return new Size(300,300);
}


MeasureOverride 中,必须调用每个子元素的 Measure 方法,传递该面板可以分配的空间。然后,布局系统根据可用大小计算每个子元素的 DesiredSize。在此示例中,我们将 100x100 分配给前 9 个子级,将 0x0 分配给其余子级。父元素分配给子级的大小可以基于传递给 MeasureOverride 方法的 availableSize 值。availableSize 的值表示该面板在布局中可以占据的区域。

调用 Measure 时,布局系统基于传递给 MeasureavailableSize 和元素的固有大小确定子元素的 DesiredSize。该固有大小由元素的 WidthHeight 属性或图像的固有大小决定。一般将 DesiredSize 设置为 availableSize 和固有大小中较小的一个值。

设置子级的 DesiredSize 后,面板必须确定要从父级中请求多少空间以及来自 MeasureOverride 重写的返回值。可以用很多方式来确定合适的值:

  • 根据所有子元素的总 DesiredSize 值计算。

  • 如当前示例中所示的预定大小。

  • 指定值很大的大小,这将允许面板留出空间排列其子级。

警告说明警告:

不返回传递给 MeasureOverrideavailableSize 值。MeasureOverride 的返回值必须是有限值,但是在某些情况下传入的 availableSize 值可以是无限值。

排列

测量处理过程完成后,将开始进行排列处理过程。在排列处理过程中,必须确定每个子??的布局槽的位置和大小并设置面板的最终大小。

下面的代码为测量一节中的 BlockPanel 演示 ArrangeOverride 方法。

//Second arrange all children and return final size of panel
protected override Size ArrangeOverride(Size finalSize)
{
//Get the collection of children
UIElementCollection mychildren = Children;

//Get total number of children
int count = mychildren.Count;

//Arrange children
//We're only allowing 9 children in this panel. More children will get a 0x0 layout slot.
int i;
for (i = 0; i < 9; i++)
{

//Get (left, top) origin point for the element in the 3x3 block
Point cellOrigin = GetOrigin(i, 3, new Size(100, 100));

//Arrange child
//Get desired height and width. This will not be larger than 100x100 as set in MeasureOverride.
double dw = mychildren[i].DesiredSize.Width;
double dh = mychildren[i].DesiredSize.Height;

mychildren[i].Arrange(new Rect(cellOrigin.X, cellOrigin.Y, dw, dh));

}

//Give the remaining children a 0x0 layout slot
for (i = 9; i < count; i++)
{
mychildren[i].Arrange(new Rect(0, 0, 0, 0));
}


//Return final size of the panel
return new Size(300, 300);
}

//Calculate point origin of the Block you are in
protected Point GetOrigin(int blockNum, int blocksPerRow, Size itemSize)
{
//Get row number (zero-based)
int row = (int)Math.Floor(blockNum / blocksPerRow);

//Get column number (zero-based)
int column = blockNum - blocksPerRow * row;

//Calculate origin
Point origin = new Point(itemSize.Width * column, itemSize.Height * row);
return origin;

}


ArrangeOverride 中,对每个子级调用 Arrange,传递 Rect。它设置父面板中子级的布局槽的原点、高度和宽度。在此示例中,根据它们在 Children 集合中的顺序,在一个 3x3 的网格单元格中放置前 9 个子级。将第一个子级放置在左上方单元格中,因此传递的 Rect 是 (0,0,100,100),这意味着它将放置在面板的左上角,宽度和高度为 100。给前 9 个子级一个 100x100 的布局槽。给其余子级一个 0x0 的布局槽。如果子级的所需大小比分配的空间大,将裁剪它。每个子元素基于其他一些布局属性(如 HorizontalAlignmentVerticalAlignmentMargin)在布局槽中定位自身。

注意说明:

在确定布局时,您的自定义面板不应考虑可设置的属性(如 VisibilityMarginMinWidth)。Silverlight 布局系统将处理所有这些属性。例如,您不需要跳过 Visibility 值为 Collapsed 的元素的布局,因为这将由布局系统来处理。

在排列每个子级后,返回面板的最终大小。这是面板将从父容器请求的大小。在此示例中,始终将 BlockPanel 设置为 300x300。

在 XAML 中创建自定义面板

为了在 XAML 中使用您的面板,必须为自定义面板类定义 XML 命名空间。然后当您创建自定义面板的实例时,使用您的 XML 命名空间引用它。

下面的代码示例演示如何创建 BlockPanel 的实例。

运行此示例

 <UserControl x:Class="BlockPanel.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:BlockPanel;assembly=BlockPanel"
>


<Grid x:Name="LayoutRoot" Background="Black">

<my:BlockPanel Background="Black" HorizontalAlignment="Left" VerticalAlignment="Top" >
<Rectangle Fill="Red" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Salmon" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Orange" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Yellow" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Lime" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Green" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Turquoise" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Blue" Height="500" Width="500" Margin="2"/>
<Rectangle Fill="Purple" Height="500" Width="500" Margin="2"/>
<TextBlock Text="This Text Does Not Appear"/>
</my:BlockPanel>

</Grid>


可滚动的内容和性能

如果您创建一个包含许多可滚动内容的自定义控件(类似于 ListBox), 并且该控件加载过程很慢或滚动不平滑,则考虑使用虚拟化。"虚拟化"是指一种技术,通过该技术,可根据屏幕上所显示的项来从大量数据项中生成 UI 元素的子集。如果在可能只有少量元素显示在屏幕上时生成许多 UI 元素,则会对应用程序的性能产生负面影响。可以通过从 VirtualizingStackPanel 派生控件,使用可滚动内容对自定义控件进行虚拟化。有关更多信息,请参见 VirtualizingStackPane


  评论这张
 
阅读(766)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018