Silverlight中定义布局面板
来源:互联网 发布:数据库程序设计 编辑:程序博客网 时间:2024/04/30 04:25
这是我阅读《Silverlight5 in Action》中一部分的笔记整理,原著中的代码有部分错误,而且注释不多,其中有些细节部分我也没搞太清楚。先做个笔记留作以后查看。
这里的实例是构建一个轨道布局的Panel,就是Panel中的所有控件是分布在一个圆形轨道上的。最终效果如下:
构建自定义布局,肯定需要先理解布局系统的工作原理,然后才能去构建。布局面板需要经过两个阶段才能完成布局,分别是测量阶段和排列阶段。布局面板的基类Panel提供了MeasureOverride和ArrangeOverride两个方法,供子类继承实现特定的布局行为。
在测量布局阶段,会对面板中Children集合InternalChildren的每个子元素(child)进行计算,测量大小。此过程是通过调用child的Measure方法来完成。
在排列布局阶段,同样会对面板中Children集合InteralChildren的每个元素调用Arrange放来完成。
首先定义自己的布局类:
在布局类中首先是定义属性,包括依赖属性和附加属性定义的方法。然后是重写MeasureOverride和ArrangeOverride方法。
namespace ControlsLib{ public class OrbitPanel : Panel { /// <summary> /// 这是一个依赖属性,表示的是OribtPanel中轨道(Orbit)的个数 /// </summary> /// <value> /// The number of orbits. /// </value> public int Orbits { get { return (int)GetValue(OrbitsProperty); } set { SetValue(OrbitsProperty, value); } } /// <summary> /// 用DependencyProperty的Register方法注册依赖属性OrbitsProperty /// </summary> public static readonly DependencyProperty OrbitsProperty = DependencyProperty.Register("Orbits", typeof(int), typeof(OrbitPanel), new PropertyMetadata(1, OnOrbitsChanged)); public static void OnOrbitsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if ((int)e.NewValue < 1) { throw new ArgumentException("Orbits must be greater than or equal to 1"); } } //The Orbit attached property in the OrbitPanel class //GetOrbit和SetOrbit定义OrbitPanel的附加属性(Attached Property)Orbit //Orbit表示控件位于第几个轨道 public static int GetOrbit(DependencyObject obj) { return (int)obj.GetValue(OrbitProperty); } public static void SetOrbit(DependencyObject obj, int value) { obj.SetValue(OrbitProperty, value); } /// <summary> /// 依赖属性Orbit利用DependencyProperty提供的RegisterAttached的方法进行注册 /// </summary> public static readonly DependencyProperty OrbitProperty = DependencyProperty.RegisterAttached("Orbit", typeof(int), typeof(OrbitPanel), new PropertyMetadata(0)); private double CalculateOrbitSpacing(Size availableSize) { double constrainingSize = Math.Min(availableSize.Width, availableSize.Height); double space = constrainingSize / 2; return space / Orbits; } private List<UIElement>[] SortElements() { var list = new List<UIElement>[Orbits]; for (int i = 0; i < Orbits; i++) { if (i == Orbits - 1) { list[i] = (from UIElement child in Children where GetOrbit(child) >= i select child).ToList<UIElement>(); } else { list[i] = (from UIElement child in Children where GetOrbit(child) == i select child).ToList<UIElement>(); } } return list; } protected override Size MeasureOverride(Size availableSize) { var sortedItems = SortElements(); double max = 0.0; foreach (List<UIElement> orbitItems in sortedItems) { if (orbitItems.Count > 0) { foreach (UIElement element in orbitItems) { element.Measure(availableSize); if (element.DesiredSize.Width > max) { max = element.DesiredSize.Width; } if (element.DesiredSize.Height > max) { max = element.DesiredSize.Height; } } } } Size desiredSize = new Size(max * Orbits * 2, max * Orbits * 2); if (Double.IsInfinity(availableSize.Height) || Double.IsInfinity(availableSize.Width)) { return desiredSize; } else { return availableSize; } } protected override Size ArrangeOverride(Size finalSize) { var sortedItems = SortElements(); double orbitSpacing = CalculateOrbitSpacing(finalSize); for (int i = 0; i < sortedItems.Length; i++ ) { List<UIElement> orbitItems = sortedItems[i]; int count = orbitItems.Count; if (count > 0) { //计算每个轨道的周长 double circumference = 2 * Math.PI * orbitSpacing * (i + 1); double slotSize = Math.Min(orbitSpacing, circumference / count); double maxSize = Math.Min(orbitSpacing, slotSize); double angleIncrement = 360 / count; double currentAngle = 0; Point centerPoint = new Point(finalSize.Width / 2, finalSize.Height / 2); for (int j = 0; j < orbitItems.Count; j++) { UIElement element = orbitItems[j]; double angle = Math.PI / 180 * (currentAngle - 90); double left = orbitSpacing * (i + 1) * Math.Cos(angle); double top = orbitSpacing * (i + 1) * Math.Sin(angle); Rect finalRect = new Rect(centerPoint.X + left - element.DesiredSize.Width / 2, centerPoint.Y + top - element.DesiredSize.Height / 2, element.DesiredSize.Width, element.DesiredSize.Height); element.Arrange(finalRect); currentAngle += angleIncrement; } } } return base.ArrangeOverride(finalSize); } }}测试代码如下:
<UserControl x:Class="CustomControls.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:clib="clr-namespace:ControlsLib;assembly=ControlsLib" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="100" /> <Setter Property="Height" Value="30" /> </Style> </Grid.Resources> <clib:OrbitPanel Orbits="3"> <Button Content="Button 1" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 2" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 3" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 4" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 5" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 6" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 7" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 8" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 9" Background="Orange"clib:OrbitPanel.Orbit="0" /> <Button Content="Button 10" Background="Blue"clib:OrbitPanel.Orbit="1" /> <Button Content="Button 11" Background="Blue"clib:OrbitPanel.Orbit="1" /> <Button Content="Button 12" Background="Blue"clib:OrbitPanel.Orbit="1" /> <Button Content="Button 13" Background="Blue"clib:OrbitPanel.Orbit="1" /> <Button Content="Button 14" Background="Blue"clib:OrbitPanel.Orbit="1" /> </clib:OrbitPanel> </Grid></UserControl>
0 0
- Silverlight中定义布局面板
- Silverlight 布局面板加控件方法
- silverlight 中 canvas布局
- Extjs中面板布局的应用
- Extjs中面板布局的应用
- 代码中定义布局
- silverlight 属性面板
- silverlight布局
- Settings中布局主题定义。
- GUI中面板作为子容器,形成布局
- tableLayoutPanel: 表格布局面板
- 组件、布局与面板
- swing 面板布局
- EXT JS 面板布局
- WrapPanel面板布局
- dbd面板的布局
- ExtJS面板与布局
- 面板组件-盒布局
- 使用css进行浏览器样式清零
- uva 445 uva 489 uva 490 uva 694(模拟)
- 黑马程序员_NSArray
- 黑马程序员 使用通配符和使用泛型变量
- Template template parameter(模板参数) example
- Silverlight中定义布局面板
- 树状数组基本操作
- i2c
- 一个测试SQL2005连接的Java程序
- 石子合并问题(动态规划)
- python的弱引用
- POJ 3259 Wormholes (Bellman)
- OpenGL绘图的基本过程是:清除缓冲区,设置当前颜色,绘制几何图元,输出图形。
- DHCP协议和dhcpcd源码分析