自定义面板类Panel

来源:互联网 发布:java直播网站源码 编辑:程序博客网 时间:2024/04/29 10:52

实现自定义面板需要实现一个抽象类Panel(Grid,StackPanel,Canvas的公共基类),通过重写此类中的方法MeasureOverride和ArrangeOverride指定面板子元素的布局行为.

这两个方法与silverlight布局的两个过程对应,第一个遍历过程是父元素确定其每一个子元素的大小,第二个遍历过程是父元素把子元素安排到相对于自身的位置上.为了完成这两项工作,面板类会访问你的派生类(派生自Panel的类)的Children属性.Children属性的类型是UIElementCollection,但你自己不能实例化UIElementCollection的对象,而且该Children对象执行一些你不知道的隐藏起来的特殊工作,所以当你需要创建类似Panel的类时,必须派生Panel类,如果你需要能以某种灵活的方式承载多个子元素的元素,那可以从Panel派生出来.

我们的面板类重写了MeasureOverride和ArrangeOverride方法,在MeasureOverride方法中.面板类调用所有子元素的Measure方法,在

ArrangeOverride方法中调用所有子元素的Arrange方法.在各个子元素的Measure和Arrange方法中又调用了自己的MeasureOverride和ArrangeOverride方法,这样一直到持续遍历完整棵树.

面板类不需要考虑如下属性,这些属性可能由元素自身或子元素进行设置:

HorizontalAlignment和VerticalAlignment

Margin

Visibility

Opacity

RenderTransform

Height, MinHeight, MaxHeight,

Width, MinWidth, MaxWidth.

这些属性能过不同的方式进行自动处理.

MeasureOverride(System.Windows.Size availableSize)

availableSize是面板类的父元素可提供的大小.

MeasureOverride方法完成两个基本工作

1.调用所有子元素的Measure方法,这是必要的,否则,子元素就没有大小.并且不能显示在屏幕上.

MeasureOverride通常都是能过Foreach语句来遍历Childern属性来完成这个操作.

2.返回面板类所需要大小.

ArrangeOverride方法的工作是把元素排列在它的表面上,通过枚举所有的子元素并分别调用它们的Arrange方法来完成.

布局时常要用到Rect.

Rect表示子元素相对父元素左上角的位置,以及子元素的大小.

 

 public class CellsPanel:Panel    {        protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)        {            int i = 0;            foreach (var item in Children)            {                if (i < 15)                {                    //为前15个元素分配100*100的布局槽,其余元素不分配                    item.Measure(new Size(100, 100));                }                else                {                    item.Measure(new Size(0, 0));                }                i++;            }            return new Size(300, 600);        }        protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)        {            int cnt = Children.Count;            for (int i = 0; i < cnt; i++)            {                Point pt =  GetCellOrigin(i);                double w, h;                w = Children[i].DesiredSize.Width;                h = Children[i].DesiredSize.Height;                Children[i].Arrange(new Rect(pt.X, pt.Y, w, h));            }            return new Size(300, 600);        }        private Point GetCellOrigin(int index)        {            int row, column;            column = index%3;            row = index/3;            int x, y;            x = column * 100;            y = row * 100;            if (column == 1)            {                y += 50;            }            Point pt = new Point(x, y);            return pt;        }    }

xaml布局文件如下

 <local:CellsPanel>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBox Text="dddd"/>                <TextBlock Text="dddd"/>            </local:CellsPanel>

运行效果如下.

 

原创粉丝点击