wpf 自定义面板

本文档展示了如何创建一个名为WrapBreakPanel的自定义WPF面板,该面板允许在特定条件下(如内容宽度超过可用空间时)在布局中插入换行符。通过使用依赖属性LineBreakBefore,可以控制元素前是否添加换行。在主程序中,此面板被用于堆叠面板内,以展示其在按钮布局中的应用。
摘要由CSDN通过智能技术生成

1 新建wpf项目

2 新建wpf UserControl类库

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace CustomControl
{
    public class WrapBreakPanel : Panel
    {


        public static bool GetLineBreakBefore(DependencyObject obj)
        {
            return (bool)obj.GetValue(LineBreakBeforeProperty);
        }

        public static void SetLineBreakBefore(DependencyObject obj, bool value)
        {
            obj.SetValue(LineBreakBeforeProperty, value);
        }
        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);
        }


        protected override Size MeasureOverride(Size availableSize)
        {
            Size currentLineSize = new Size();
            Size panelSize = new Size();

            foreach (UIElement element in base.InternalChildren)
            {
                element.Measure(availableSize);
                Size desiredSize = element.DesiredSize;

                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;
        }


        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)                  
                    {
                        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;
            }
        }
    }
}

3 主程序

<Window x:Class="CustomControlApp.WrapBreakPanelTest"
        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:CustomControlApp"
        xmlns:lib="clr-namespace:CustomControl;assembly=CustomControl"
        mc:Ignorable="d"
        Title="WrapBreakPanelTest" Height="450" Width="800">
    <Grid>

        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Margin" Value="3"></Setter>
                    <Setter Property="Padding" Value="3"></Setter>
                </Style>
            </StackPanel.Resources>
            <TextBlock Padding="5" Background="LightGray">Content above the WrapBreakPanel.</TextBlock>
            <lib:WrapBreakPanel>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
                <Button lib:WrapBreakPanel.LineBreakBefore="True" FontWeight="Bold">Button with Break</Button>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
                <Button>No Break Here</Button>
            </lib:WrapBreakPanel>
            <TextBlock Padding="5" Background="LightGray">Content below the WrapBreakPanel.</TextBlock>
        </StackPanel>
    </Grid>
</Window>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WPF自定义工控触控键盘是一种特殊的应用程序,主要是为了更好地满足工业控制领域的需求。在传统的工控设备中,物理键盘通常很大,不便于移动和安装。而且,有时需要工程师们花费大量精力来编写复杂的驱动程序。 WPF自定义工控触控键盘可以解决这些问题。相对于传统物理键盘,它更加轻便和灵活;更重要的是,只需要少量的代码即可实现高度个性化的特征,大大减少了工程师们的工作量。因此,WPF自定义工控触控键盘已成为很多工业控制领域的首选方案。 在实际应用过程中,WPF自定义工控触控键盘通常有以下特点: 1. 优秀的触摸感应效果,能够更好地适应不同的触摸屏幕需求。 2. 可以高度定制化,可以根据客户的需求来进行UI界面和交互方式的调整,满足更广泛的应用需求。 3. 实时性高,能够满足各类复杂的系统应用,保证数据的实时采集与处理。 4. 代码量少,相对于传统的物理键盘,它无需编写太多的驱动程序,能够更加高效地进行开发。 总之,WPF自定义工控触控键盘具有很多优势,并逐渐成为工业控制领域的主流方案。它能够为用户提供更加灵活和可定制的应用方案,带来更高效、安全的工业生产和操作体验。 ### 回答2: WPF自定义工控触控键盘是一种便捷的实现机器人人机交互的方法。这种自定义工控触控键盘根据机器人实际需求,以可视化的方式设计界面,并实现可定制的功能,既简单又灵活。 在WPF自定义工控触控键盘中,我们可以使用WPF中的控件和布局来定义机器人控制面板。机器人控制面板可以通过添加按钮、文本框、下拉框等控件进行快捷控制。在这个过程中,我们可以使用各种布局以确保面板的外观精美和可用性。 使用WPF自定义工控触控键盘时还可以使用许多流行的控件库,使设计变得更加简单,如Telerik、Syncfusion、DevExpress等,这些库提供了大量可重用的控件和样式,可以轻松创建可定制化的控制面板以及其他用户界面。 WPF自定义工控触控键盘不仅可以使机器人控制面板可视化,也可以将机器人控制与电脑的其他硬件设备、应用程序和网络设备有机地结合在一起。例如,可以通过编写代码将机器人的控制指令发送到网络设备,从而实现通过互联网控制机器人。 总之,WPF自定义工控触控键盘使机器人控制面板的设计更加自由和灵活,使机器人控制更加便捷和高效。这种自定义工控触控键盘可以实现各种机器人任务的快速实现,是机器人应用领域的重要技术之一,同时也是人机交互领域不可或缺的一部分。 ### 回答3: WPF是一种用于.NET框架的GUI开发工具,可以用来创建各种桌面应用程序。在工控应用领域,触控键盘已经成为常见的工具,可以用来实现人机交互,提高工作效率。通过WPF自定义工控触控键盘,可以实现更加灵活和个性化的功能。 WPF提供了许多UI控件,可以用来创建各种视觉元素。开发者可以利用这些控件创建自定义的触控键盘,并将其集成到工控应用中。例如,可以使用按钮控件来创建各种键位,使用文本框控件来显示输入的字符等等。WPF还提供了丰富的样式和模板功能,可以用来美化自定义键盘的外观,并实现与应用程序的整体风格统一。 在工控应用中,触控键盘需要具备一些特殊的功能,如支持多种输入方式(单击、滑动、长按等)、精准的触控响应和持久化的自定义设置等。为了实现这些功能,开发者需要对WPF的触摸事件机制有深入的理解,并根据实际需求进行相应的处理和优化。 总之,通过WPF自定义工控触控键盘,可以提高工控应用的交互性和实用性,满足不同场景下的需求,同时也能增加开发者的编程技能和经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值