自定义容器

1、Panel.ZIndex

所有容器都支持,调整子项的层级

Z轴,是向屏幕外延伸的方向,高度

 小于零

拖放场景,放到哪一个放到最上面,可以设置Panel.ZIndex=1

<InkCanvas EditingMode="Select">

也可以选中鼠标放到边缘出现4箭头图标的时候,拖放,但是必须后面的元素永远都会是在最上面

 

 

2、自定义布局原理

所有控件都要自己的特色

所有控件都继承子Panel

 从上往下的堆叠

第一个子项

第二个子项在第一个子项高度的下面

第三个子项在第1个+第二个高度的下面

 

测量+排列

位置问题

数值性的坐标

X=0,Y=前面所有子项的高度

 

所有子项:this.InternalChildren

 

参数Size availableSize

所有子项所需要的尺寸,如果大于视窗,就是大于视窗的尺寸

 

创建窗口,使用自定义<local:ZysStackPanel>

必须生成一下,才可以引用

 

自定义区域划分

期望尺寸:item.DesiredSize 

设置高度和宽度就用这个期望尺寸获取

没设置就是字体占的大小尺寸

 

排列时候用到的就是前面测量返回的尺寸

高度累加,自上而下依次排列

        override protected Size MeasureOverride(Size availableSize)
        {
            Size size = new Size();
            foreach (UIElement child in InternalChildren)
            {
                child.Measure(availableSize);
                size.Width = Math.Max(size.Width, child.DesiredSize.Width);
                size.Height += child.DesiredSize.Height;
            }
            return size;
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            //return base.ArrangeOverride(finalSize);
            double height = 0;
            foreach (UIElement child in InternalChildren)
            {
                child.Arrange(new Rect(0, height, finalSize.Width, child.DesiredSize.Height));
                height += child.DesiredSize.Height;
            }
            return finalSize;
        }

 

3、需求 调整顺序

依赖附加属性

propa快捷,改为Index,序号

 窗口调用就可以出现Index

 普通属性不支持

 

 

排序代码

    public class ZysStackPanel : Panel
    {
        // 从上向下的累积
        // 第一个子项  第一个
        // 第二个子项  在第一个子项的高度下面
        // 第三个子项  在第二个子项的高度+第一个子项的高度
        // 。。。。。

        // 两个过程:
        // 测量:
        // 排列

        List<ListItem> children = new List<ListItem>();
        // 测量:主要是对子控件进行期望尺寸的测量
        protected override Size MeasureOverride(Size availableSize)
        {
            //Size size = new Size(availableSize.Width / 4, availableSize.Height);
            // 记录所有子控件的整体高度
            double height = 0;
            // 遍历子控件,对控件一一进行测量动作
            foreach (FrameworkElement item in this.InternalChildren)
            {
                int index = ZxStackPanel.GetIndex(item);
                // 添加到临时集合,供后续排序用
                children.Add(new ListItem { Control = item, Index = index });
                // 控件测量->得到控件的期望尺寸DesiredSize
                item.Measure(availableSize);
                //
                height += item.DesiredSize.Height;
            }

            // 通过依赖附加属性对子控件进行排序
            children = children.OrderBy(c => c.Index).ToList();
            // 根据指定序号进行调整
            int i = 0;
            while (i < children.Count)
            {
                if (children[i].Index > 0)
                {
                    ListItem item = children[i];
                    children.RemoveAt(i);
                    children.Insert(item.Index, item);
                }
                else
                    i++;
            }

            // 返回所有子控件所需要的Size,可能比容器大小要大:availableSize
            return new Size(availableSize.Width, height);
        }

        // 排列:最终子控件在放在哪个位置(坐标)上
        // finalSize等于MeasureOverride返回值
        protected override Size ArrangeOverride(Size finalSize)
        {
            // 记录所有子控件的整体高度
            double height = 0;
            foreach (ListItem item in children)
            {
                // 将Item子项放到特定的位置 ,主要是在Rect的X和Y,大小由Rect的Width和Height决定
                item.Control.Arrange(new Rect(0, height, finalSize.Width, item.Control.DesiredSize.Height));
                //
                height += item.Control.DesiredSize.Height;
            }

            return finalSize;
        }


        // 需求:StackPanel中的子项进行顺序调整
        public static int GetIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(IndexProperty);
        }

        public static void SetIndex(DependencyObject obj, int value)
        {
            obj.SetValue(IndexProperty, value);
        }
        public static readonly DependencyProperty IndexProperty =
            DependencyProperty.RegisterAttached("Index", typeof(int), typeof(ZxStackPanel), new PropertyMetadata(0));

        //private int _index;

        //public int Index
        //{
        //    get { return _index; }
        //    set { _index = value; }
        //}

        // 

        // 指定子项的区域大小  大中小
    }

    class ListItem
    {
        public FrameworkElement Control { get; set; }
        public int Index { get; set; }
    }
View Code

 

 

如果不知道用哪个

直接用grid

 

自定义个性化需求

磁铁式菜单,瀑布流(最短列往后排),

WarpPanel,后面如果是一个组,折行排列

对于不同控件理解更深入

 

菜单,用得少

    <Menu>    
        <Menu.ContextMenu>
            <ContextMenu>
                <MenuItem Header="鼠标右键出来"/>
                <Button Content="按钮" />
            </ContextMenu>
        </Menu.ContextMenu>
        <MenuItem Header="首页">
            <MenuItem Header="子菜单">
                <MenuItem Header="孙菜单"/>
            </MenuItem>
        </MenuItem>
        <MenuItem Header="设备管理"/>
        <MenuItem Header="仓库管理"/>
        <MenuItem Header="报表中心"/>
    </Menu>

 

posted on 2025-03-27 14:46  张彦山  阅读(25)  评论(0)    收藏  举报