自定义面板类Panel

实现自定义面板需要实现一个抽象类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>

运行效果如下.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值