自定义容器
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; } }
如果不知道用哪个
直接用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>
浙公网安备 33010602011771号