WPF中Grid自动布局

ops/2025/1/15 18:48:07/

控件功能

根据自定义行和列,快速进行排列,能够进行自定义控件间距离,减少元素进行定义间距,同时能更好的维护界面排序。

代码部分

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;namespace WPFApp
{public class AutoGrid : Grid{/// <summary>/// 列定义 例如: "100,*,100"  "100 * 100"/// </summary>[Category("Layout")]public string Columns{get { return (string)GetValue(ColumnsProperty); }set { SetValue(ColumnsProperty, value); }}public static readonly DependencyProperty ColumnsProperty =DependencyProperty.Register(nameof(Columns), typeof(string), typeof(AutoGrid), new PropertyMetadata("", ColumnsChanged));/// <summary>/// 行定义 例如: "100,*,100"  "100 * 100"    /// </summary>[Category("Layout")]public string Rows{get { return (string)GetValue(RowsProperty); }set { SetValue(RowsProperty, value); }}public static readonly DependencyProperty RowsProperty =DependencyProperty.Register(nameof(Rows), typeof(string), typeof(AutoGrid), new PropertyMetadata("", RowsChange));/// <summary>/// 排列方式/// </summary>[Category("Layout")]public Orientation Orientation{get { return (Orientation)GetValue(OrientationProperty); }set { SetValue(OrientationProperty, value); }}public static readonly DependencyProperty OrientationProperty =DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(AutoGrid), new PropertyMetadata(Orientation.Horizontal));/// <summary>/// 元素之间Margin/// </summary>[Category("Layout")]public Thickness? ChildMargin{get { return (Thickness?)GetValue(ChildMarginProperty); }set { SetValue(ChildMarginProperty, value); }}public static readonly DependencyProperty ChildMarginProperty =
DependencyProperty.Register(nameof(ChildMargin), typeof(Thickness?), typeof(AutoGrid), new PropertyMetadata((Thickness?)null, OnChildMarginChanged));/// <summary>/// 移除多余的元素/// </summary>public bool IsRemoveEleme { get; set; } = true;private static void OnChildMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var grid = d as AutoGrid;foreach (UIElement child in grid.Children){if (grid.ChildMargin.HasValue)child.SetValue(FrameworkElement.MarginProperty, grid.ChildMargin);elsechild.SetValue(FrameworkElement.MarginProperty, DependencyProperty.UnsetValue);}}protected override Size MeasureOverride(Size constraint){PerformLayout();return base.MeasureOverride(constraint);}private void PerformLayout(){int colCount = this.ColumnDefinitions.Count;int rowCount = this.RowDefinitions.Count;if (colCount == 0 || rowCount == 0) return;var position = 0;foreach (UIElement child in Children){var childIsCollapsed = child.Visibility == Visibility.Collapsed;if (childIsCollapsed) continue;if (this.Orientation == Orientation.Horizontal){//从左往右,再从上往下var row = Clamp(position / colCount, rowCount - 1);var col = Clamp(position % colCount, colCount - 1);Grid.SetRow(child, row);Grid.SetColumn(child, col);Grid.SetRowSpan(child, 1);position += Grid.GetColumnSpan(child);}else{//从上往下,再从左往右var row = Clamp(position % rowCount, rowCount - 1);var col = Clamp(position / rowCount, colCount - 1);Grid.SetRow(child, row);Grid.SetColumn(child, col);Grid.SetColumnSpan(child, 1);position += Grid.GetRowSpan(child);}//设置Marginif (ChildMargin.HasValue){child.SetValue(FrameworkElement.MarginProperty, ChildMargin);}else{child.SetValue(FrameworkElement.MarginProperty, DependencyProperty.UnsetValue);}}//移除无法分配的元素if (IsRemoveEleme && Children.Count > colCount * rowCount){Children.RemoveRange(colCount * rowCount, Children.Count - colCount * rowCount);}}private int Clamp(int value, int max){return (value > max) ? max : value;}private static void RowsChange(DependencyObject d, DependencyPropertyChangedEventArgs e){if (string.IsNullOrEmpty((string)e.NewValue)) return;var grid = (AutoGrid)d;grid.RowDefinitions.Clear();GridLength[] defs = GridLengthParse((string)e.NewValue);foreach (var def in defs){grid.RowDefinitions.Add(new RowDefinition(){Height = def});}}private static void ColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (string.IsNullOrEmpty((string)e.NewValue)) return;var grid = (AutoGrid)d;grid.ColumnDefinitions.Clear();GridLength[] defs = GridLengthParse((string)e.NewValue);foreach (var def in defs){grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = def});}}public static GridLength[] GridLengthParse(string text){string[] tokens = text.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries);GridLength[] defineResult = new GridLength[tokens.Length];for (int i = 0; i < tokens.Count(); i++){string curStr = tokens[i];double value = 0.0;//Starif (curStr.Contains('*')){if (!double.TryParse(curStr.Replace("*", ""), out value)){value = 1.0;}defineResult[i] = new GridLength(value, GridUnitType.Star);}//Pixelif (double.TryParse(curStr, out value)){defineResult[i] = new GridLength(value, GridUnitType.Pixel);continue;}//AutodefineResult[i] = GridLength.Auto;}return defineResult;}}
}

使用示例

<Windowx:Class="WPFApp.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:local="clr-namespace:WPFApp"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Title="MainWindow"Width="800"Height="450"mc:Ignorable="d"><Window.DataContext><local:MainWindowViewModel /></Window.DataContext><local:AutoGridChildMargin="10,10,0,0"Columns="100 200 300 400"Orientation="Horizontal"Rows="200 *"><TextBlock Text="1" /><TextBlock Text="2" /><TextBlock Text="3" /><TextBlock Text="4" /><TextBlock Text="5" /><TextBlock Text="6" /><TextBlock Text="7" /><TextBlock Text="8" /><TextBlock Text="9" /><TextBlock Text="10" /><TextBlock Text="11" /><TextBlock Text="12" /></local:AutoGrid>
</Window>

图示

在这里插入图片描述


http://www.ppmy.cn/ops/150360.html

相关文章

长安“战疫”网络安全公益赛的一些随想

起因 今年刚进入大学&#xff0c;开始带校队&#xff0c;为了培养校队新成员&#xff0c;也就一直计划着和当地的一些高校合作交流&#xff0c;但是由于种种原因一直被搁置下来。正巧学校信息中心和四叶草有一个培训项目的合作&#xff0c;学校的网安协会也算是沾了光成为了培…

UDP、TCP特性

1.简介 在传输层中&#xff0c;最重要的两个协议就是UDP协议和TCP协议&#xff0c;其中TCP协议更为重要。 对于TCP协议&#xff0c;其性质为有连接、可靠传输、面向字节流、全双工&#xff1b; 对于UDP协议&#xff0c;其性质为无连接、不可靠传输、面向数据报、全双工。 下…

hive知识体系

hive知识体系 hive知识体系 链接: 1Hive概览 链接: 2Hive表类型 链接: 3Hive数据抽样 链接: 4Hive计算引擎 链接: 5Hive存储与压缩 链接: 6Hive Sql 大全 链接: 6Hive Sql 大全-Hive 函数 链接: 6Hive Sql 大全-窗口函数 链接: 7Hive执行计划 链接: 8Hive SQL底层执行原理 链接…

探索学习 Python 的有效方式方法

Python 作为当今最热门的编程语言之一&#xff0c;吸引着无数编程爱好者和专业人士。然而&#xff0c;对于初学者来说&#xff0c;如何高效地学习 Python 可能是一个挑战。以下是一些实用的 Python 学习方法。 一、打好基础&#xff1a;语法与数据结构 深入理解语法 Python 以…

Spring Boot性能提升的核武器,速度提升500%!

虚拟线程是 Java 21 引入的一个新特性&#xff0c;用于简化并发编程。它与传统的操作系统线程相比&#xff0c;具有显著的优势&#xff1a; 轻量级&#xff1a;虚拟线程由 JVM 管理&#xff0c;而非操作系统&#xff0c;因此它们的内存占用和创建成本远低于传统线程。理论上&am…

后端接口获取的对象包含图片,渲染后端图片,拼接地址渲染,循环列表,vue+uniapp

如果是全链接的好说&#xff0c;直接item.img就行&#xff0c; <image :src"item.icon" ></image> 如果是加背景就是:style"[{backgroundImage:url(item.img)}]" 另外一种就是后端返回文件名字或者一部分链接&#xff0c;前面需要拼接上…

matlab使用 BP 神经网络进行数据预测的完整流程,包括数据读取、数据预处理等等

%% 初始化程序 warning off % 关闭报警信息 close all % 关闭所有图窗 clear % 清空变量 clc % 清空命令行 setdemorandstream(172) %设置随机种子为1%% 读取数据 data xlsread(Y.xlsx); %% 划分训练集…

朝天椒USB服务器在万家基金的前置机应用案例

随着云计算和大数据技术的快速发展&#xff0c;万家基金管理有限公司对数据中心的性能、可靠性和可扩展性提出了更高的要求。在这样的背景下&#xff0c;万家基金选择了超融合虚拟化技术作为其数据中心的核心技术&#xff0c;旨在通过虚拟化技术实现资源的按需分配和弹性扩展&a…