首页 > 其他分享 >【自定义控件】WrapBeakPanel-自定义代有换行功能的Panel

【自定义控件】WrapBeakPanel-自定义代有换行功能的Panel

时间:2022-11-28 06:44:05浏览次数:45  
标签:控件 currentLineSize 自定义 WrapBeakPanel panelSize Height Width desiredSize Size

自定义代有换行功能的Panel

WrapBreakPanel.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace MyPanels
{
    public class WrapBreakPanel:Panel
    {
        
         
       
        public static readonly DependencyProperty LineBreakBeforeProperty;

        static WrapBreakPanel()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.AffectsArrange = true;
            metadata.AffectsMeasure = true;


            LineBreakBeforeProperty =
                 DependencyProperty.RegisterAttached("LineBreakBefore", typeof(bool), typeof(WrapBreakPanel), metadata);
        } 


 
        public static Boolean GetLineBreakBefore(UIElement element)
        {
            return (bool)element.GetValue(LineBreakBeforeProperty);
      
        }

        public static void SetLineBreakBefore(UIElement element, Boolean value)
        {
            element.SetValue(LineBreakBeforeProperty, value);
          
        }


        /// <summary>
        /// 测量阶段 
        /// 测量WrapBreakPanel 所要的期望大小(height,width)
        /// Desired Size ≤ Actual Size ≤ Available Size
        /// Desired Size:期望尺寸是子元素想要的尺寸; 对整个UI页面的检测,并询问每个元素的期望尺寸
        /// Actual Size:实际尺寸是父元元素分配给子元素的最终尺寸。
        /// Avilable Size:可用尺寸是测量阶段的初始约束值,即父元素愿意给子元素的最大空间值;
        /// 
        /// </summary>
        /// <param name="availableSize">可用大小(height,width)</param>
        /// <returns>所要的期望大小(height,width)</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
          

            Size currentLineSize = new Size();
            Size panelSize = new Size();
            foreach (UIElement element in base.InternalChildren)
            {
                //1、传入可以用大小,计算完后得到元素的期望值 询问孩子:你想要多大的空间显示自己?
                element.Measure(availableSize);

                ///2、获取元素的期望大小 孩子接到询问后,根据父给的availableSize以及自己的一些限制,比如Margin,Width,等等,
                ///孩子回答:我想要XXX大小的空间。
                Size desiredSize = element.DesiredSize;

               
                //3、父拿到孩子给的期望的空间大小后,根据自己的策略开始真正给孩子分配空间,就进入第二个子过程。
                //判断此元素是否是 断点元素
                if (GetLineBreakBefore(element) || currentLineSize.Width + desiredSize.Width > availableSize.Width)
                {
                    //切换到新行(要么是因为元素请求了它,要么是因为空间用完了)。
                    panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
                    panelSize.Height += currentLineSize.Height;
                    currentLineSize = desiredSize;

                    //如果元素太宽,不能使用最大宽度的行,只需给它一个单独的行。
                    if (desiredSize.Width > availableSize.Width)
                    {
                        panelSize.Width = Math.Max(desiredSize.Width, panelSize.Width);
                        panelSize.Height += desiredSize.Height;
                        currentLineSize = new Size();
                    } 

                 

                }
                else
                {
                    //继续添加到当前行。
                    currentLineSize.Width += desiredSize.Width;

                    //确保该行与它的最高元素一样高。
                    currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);

                   

                }
            }
                panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
                panelSize.Height += currentLineSize.Height;
                return panelSize;
 

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="arrangeBounds"></param>
        /// <returns>实即大小</returns>
        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            int firstInLine = 0;

            Size currentLineSize = new Size();

            double accumulatedHeight = 0;

            UIElementCollection elements = base.InternalChildren;
            for (int i = 0; i < elements.Count; i++)
            {

                Size desiredSize = elements[i].DesiredSize;

                if (GetLineBreakBefore(elements[i]) || currentLineSize.Width + desiredSize.Width > arrangeBounds.Width) //need to switch to another line
                {
                    arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, i);

                    accumulatedHeight += currentLineSize.Height;
                    currentLineSize = desiredSize;

                    if (desiredSize.Width > arrangeBounds.Width) //the element is wider then the constraint - give it a separate line                    
                    {
                        arrangeLine(accumulatedHeight, desiredSize.Height, i, ++i);
                        accumulatedHeight += desiredSize.Height;
                        currentLineSize = new Size();
                    }
                    firstInLine = i;
                }
                else //continue to accumulate a line
                {
                    currentLineSize.Width += desiredSize.Width;
                    currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
                }
            }

            if (firstInLine < elements.Count)
                arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, elements.Count);

            return arrangeBounds;
        }

        private void arrangeLine(double y, double lineHeight, int start, int end)
        {
            double x = 0;
            UIElementCollection children = InternalChildren;
            for (int i = start; i < end; i++)
            {
                UIElement child = children[i];
                child.Arrange(new Rect(x, y, child.DesiredSize.Width, lineHeight));
                x += child.DesiredSize.Width;
            }
        }



    }
}

xaml.cs

<Window x:Class="WrapBreakPanel.MainWindow"
        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:local="clr-namespace:WrapBreakPanel" xmlns:my="clr-namespace:MyPanels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Margin" Value="3"></Setter>
                    <Setter Property="Padding" Value="5"/>
                </Style>
            </StackPanel.Resources>
            <TextBlock Padding="5" Background="LightGray">Content above the WrapBreakPanel.</TextBlock>
            <my:WrapBreakPanel>
                <Button  >No1 Break Here</Button>
                <Button my:WrapBreakPanel.LineBreakBefore="True" FontWeight="Bold">No2 Break Here</Button>
                <Button>No3 Break Here</Button>
                <Button>No4 Break Here</Button>
                <Button my:WrapBreakPanel.LineBreakBefore="True" FontWeight="Bold">Button with Break</Button>
                <Button>No4 Break Here</Button>
                <Button>No5 Break Here</Button>
                <Button>No6 Break Here</Button>
                <Button>No7 Break Here</Button>
            </my:WrapBreakPanel>
            <TextBlock Padding="5" Background="LightGray">Content below the WrapBreakPanel.</TextBlock>
        </StackPanel>
    </Grid>
</Window>

 

效果

 

标签:控件,currentLineSize,自定义,WrapBeakPanel,panelSize,Height,Width,desiredSize,Size
From: https://www.cnblogs.com/cdaniu/p/16931239.html

相关文章

  • 判断素数(自定义函数)
    这篇和前面那个不同,是用自定义函数来写的#pragmawarning(disable:4996)#include<stdio.h>#include<math.h>//sqrt的头文件//sqrt(X)-对括号里的数开平方intpanduansushu(int......
  • DRF过滤、排序、异常处理、自定义Response、分页
    DRF过滤、排序、异常处理、自定义Response、分页目录DRF过滤、排序、异常处理、自定义Response、分页过滤局部过滤排序异常处理封装Response对象分页三种分页方式PageNumb......
  • Django自定义系列
    Django自定义系列目录Django自定义系列模板层-自定义过滤器、标签、inclusion_tag自定义过滤器(最多两个参数)自定义过滤器调用自定义标签(可以有多个参数)自定义标签调用自定......
  • Java Excel导出动态自定义单元格样式
    根据表格内容定义单元格样式效果图:文章描述两种,一种创建生成时定义样式,另一种在excel在写入文件前修改样式关键代码一/***数据动态设置样式*......
  • jquery011-自定义函数-执行
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><bodystyle="width:980px;margin:0auto"><h1>例子1</h1><......
  • jquery010-自定义-自执行-封闭
    一,jQuery扩展:-$.extend({函数名:function(){}})$.方法-$.fn.extend({函数名:function(){}})......
  • Zoteron自定义引文样式
    前言要使用的参考文献格式与Zotero官方的略有不同,生成后逐个修改又太麻烦,所以对样式文件根据个人需求做了修改,在此感谢原作者的贡献(每个位置都标有注释,好评!)修改内容1.......
  • SAP UI5 Table 控件数据进行 Excel 导出时如何进行格式控制试读版
    本教程的前一步骤,我们成功的将sap.m.Table控件里显示的数据导出到了本地Excel文件中。下图是使用sap.m.Table显示的表格页面:下面是点击上图右上角Excel导出按钮......
  • 关于 SAP UI5 XML 视图里控件事件处理函数名称中的 . (点号) 问题的讨论试读版
    本教程一位学习者向笔者提问:关于XML视图里控件事件绑定的处理函数名称,网络上找到的SAPUI5源代码,有的函数名前缀包含一个.,有的函数名中间通过.作为分割,有的函数......
  • MFC-Edit编辑框控件
         ......