示例:WPF中Grid显示网格线的几种方式

news/2024/9/23 18:30:15/

一、目的:介绍一下WPF中Grid显示网格线的几种方式


二、几种方式


1、重写OnRender绘制网格线(推荐)

效果如下:

实现方式如下:

    public class LineGrid : Grid{private readonly Pen _pen;public LineGrid(){_pen = new Pen(SystemColors.ActiveBorderBrush, 1);_pen.Freeze();}protected override void OnRender(DrawingContext dc){base.OnRender(dc);foreach (RowDefinition item in this.RowDefinitions){dc.DrawLine(_pen, new Point(0, item.Offset), new Point(this.ActualWidth, item.Offset));}dc.DrawLine(_pen, new Point(0, this.ActualHeight), new Point(this.ActualWidth, this.ActualHeight));foreach (ColumnDefinition item in this.ColumnDefinitions){dc.DrawLine(_pen, new Point(item.Offset, 0), new Point(item.Offset, this.ActualHeight));}dc.DrawLine(_pen, new Point(this.ActualWidth, 0), new Point(this.ActualWidth, this.ActualHeight));}}
                    <local:LineGrid Margin="50"><Grid.RowDefinitions><RowDefinition /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition Width="100" /></Grid.ColumnDefinitions><TextBlockGrid.Row="0"Grid.RowSpan="2"Grid.Column="5"Margin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Background="White"Text="LineGrid" /><LabelMargin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"HorizontalContentAlignment="Center"VerticalContentAlignment="Center"Background="White"Content="Center"FontSize="50" /></local:LineGrid>

优点:通过OnRender绘制复杂度低,性能较好

缺点:需要单独定义LineGrid类重写OnRender ,但相对来说实现比较简单,复用性比较高

2、使用ShowGridLines属性

效果如下:

 实现代码
                    <Grid Margin="50" ShowGridLines="True"><Grid.RowDefinitions><RowDefinition /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition Width="100" /></Grid.ColumnDefinitions><TextBlockGrid.Row="0"Grid.RowSpan="2"Grid.Column="5"Margin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Background="White"Text="LineGrid" /><LabelMargin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"HorizontalContentAlignment="Center"VerticalContentAlignment="Center"Background="White"Content="Center"FontSize="50" /></Grid>

优点:Grid自带功能,直接设置 ShowGridLines="True"即可

缺点:样式固定且单一,一般来说是不能满足需求

3、使用Adorner绘制

效果如下:

实现代码:
定义Adorner
    public class GridLineAdorner : Adorner{public GridLineAdorner(UIElement adornedElement) : base(adornedElement){}protected override void OnRender(DrawingContext dc){base.OnRender(dc);Grid grid = this.AdornedElement as Grid;if (grid == null)return;Pen pen = new Pen(SystemColors.HighlightBrush, 1);foreach (RowDefinition item in grid.RowDefinitions){dc.DrawLine(pen, new Point(0, item.Offset), new Point(this.ActualWidth, item.Offset));}dc.DrawLine(pen, new Point(0, grid.ActualHeight), new Point(this.ActualWidth, this.ActualHeight));foreach (ColumnDefinition item in grid.ColumnDefinitions){dc.DrawLine(pen, new Point(item.Offset, 0), new Point(item.Offset, this.ActualHeight));}dc.DrawLine(pen, new Point(this.ActualWidth, 0), new Point(this.ActualWidth, this.ActualHeight));}}

(注:这部分目前没有实现Rowspan和Columnspan网线的遮挡,有需求的可以使用PushClip方式实现) 

 Xaml中添加代码
        <AdornerDecorator><Grid Margin="50" Loaded="GridLine_Loaded"><Grid.RowDefinitions><RowDefinition /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /><RowDefinition Height="50" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition Width="100" /></Grid.ColumnDefinitions><TextBlockGrid.Row="0"Grid.RowSpan="2"Grid.Column="5"Margin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Background="White"Text="LineGrid" /><LabelMargin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"HorizontalContentAlignment="Center"VerticalContentAlignment="Center"Background="White"Content="Center"FontSize="50" /></Grid></AdornerDecorator>
在Loaded时给Grid添加Adoner
        private void GridLine_Loaded(object sender, RoutedEventArgs e){Grid grid = sender as Grid;GridLineAdorner gridLineAdorner = new GridLineAdorner(grid);var layer = AdornerLayer.GetAdornerLayer(grid);layer.Add(gridLineAdorner);}

 优点:定义成Adorner复用性比较高

 缺点:实现和添加相对复杂些,但一劳永逸,也可以把Loaded部分封装成附加属性调用这样就可以不用单独处理事件

4、使用GridLineAttach附加属性,添加Border的方式绘制

效果如下:

实现代码:
定义附加属性 
    public class GridLineAttach{public static bool GetUse(DependencyObject obj){return (bool)obj.GetValue(UseProperty);}public static void SetUse(DependencyObject obj, bool value){obj.SetValue(UseProperty, value);}public static readonly DependencyProperty UseProperty =DependencyProperty.RegisterAttached("Use", typeof(bool), typeof(GridLineAttach), new PropertyMetadata(default(bool), OnUseChanged));static public void OnUseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){Grid grid = d as Grid;if (grid == null)return;bool n = (bool)e.NewValue;grid.Loaded -= Grid_Loaded;if (n)grid.Loaded += Grid_Loaded;}private static void Grid_Loaded(object sender, RoutedEventArgs e){Grid grid = sender as Grid;var controls = grid.Children;var count = controls.Count;for (int i = 0; i < count; i++){var item = controls[i] as FrameworkElement;var border = new Border(){BorderBrush = SystemColors.ActiveBorderBrush,BorderThickness = new Thickness(1)};var row = Grid.GetRow(item);var column = Grid.GetColumn(item);var rowspan = Grid.GetRowSpan(item);var columnspan = Grid.GetColumnSpan(item);Grid.SetRow(border, row);Grid.SetColumn(border, column);Grid.SetRowSpan(border, rowspan);Grid.SetColumnSpan(border, columnspan);grid.Children.Add(border);}}}
给Grid添加附加属性
                    <Grid Margin="50" local:GridLineAttach.Use="True"><Grid.RowDefinitions><RowDefinition /><RowDefinition Height="50" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition Width="100" /></Grid.ColumnDefinitions><TextBlockGrid.Row="0"Grid.RowSpan="2"Grid.Column="5"Margin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Background="White"Text="LineGrid" /><LabelMargin="1"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"HorizontalContentAlignment="Center"VerticalContentAlignment="Center"Background="White"Content="Center"FontSize="50" /><TextBlock Text="1" Grid.Row="1"/></Grid>

优点:定义成附加属性复用性比较高

缺点:额外添加了Border元素,对于数据量比较大的情况增加了渲染压力

需要了解的知识点 

Grid 类 (System.Windows.Controls) | Microsoft Learn

Adorner 类 (System.Windows.Documents) | Microsoft Learn

AdornerLayer 类 (System.Windows.Documents) | Microsoft Learn

AdornerDecorator 类 (System.Windows.Documents) | Microsoft Learn

UIElement.OnRender(DrawingContext) Method (System.Windows) | Microsoft Learn

Grid.ShowGridLines Property (System.Windows.Controls) | Microsoft Learn

Border 类 (System.Windows.Controls) | Microsoft Learn

System.Windows.Controls 命名空间 | Microsoft Learn

控件库 - WPF .NET Framework | Microsoft Learn

WPF 介绍 | Microsoft Learn

XAML概述 - WPF .NET | Microsoft Learn

Windows Presentation Foundation 简介 - WPF .NET | Microsoft Learn

使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn

源码地址

GitHub - HeBianGu/WPF-ControlDemo: 示例

GitHub - HeBianGu/WPF-ControlBase: Wpf封装的自定义控件资源库

GitHub - HeBianGu/WPF-Control: WPF轻量控件和皮肤库

了解更多

适用于 .NET 8 的 WPF 的新增功能 - WPF .NET | Microsoft Learn

适用于 .NET 7 的 WPF 的新增功能 - WPF .NET | Microsoft Learn

System.Windows.Controls 命名空间 | Microsoft Learn

Reference Source

Sysinternals - Sysinternals | Microsoft Learn

Windows app development documentation - Windows apps | Microsoft Learn

欢迎使用 Expression Blend | Microsoft Learn

https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/?view=netdesktop-7.0&WT.mc_id=MVP_380318

https://github.com/HeBianGu

HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频


http://www.ppmy.cn/news/1529442.html

相关文章

【LLM】Ollama:本地大模型使用

本指南将详细介绍如何在Linux系统上使用Ollama进行本地大模型的快速部署与管理。通过Docker容器化技术&#xff0c;您可以轻松部署Ollama及其WebUI&#xff0c;实现通过浏览器访问和管理大型语言模型。 快速部署&#xff0c;Web访问 安装Docker 根据操作系统下载并安装 Dock…

openssl 生成多域名 多IP 的数字证书

openssl.cnf 文件内容&#xff1a; [req] default_bits 2048 distinguished_name req_distinguished_name copy_extensions copy req_extensions req_ext x509_extensions v3_req prompt no [req_distinguished_name] countryName CN stateOrProvinceName GuangDong l…

音视频入门基础:AAC专题(6)——FFmpeg源码中解码ADTS格式的AAC的Header的实现

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…

Lingo求解器基本语法

Lingo是一款用于线性规划和整数规划的数学建模和求解软件&#xff0c;被广泛应用于运筹学、生产优化、供应链管理等领域。今天与大家一起来熟悉一下它的基本语法 Lingo基本语法 1、定义目标函数为MIN&#xff0c;MAX. 2、以一个分号“&#xff1b;”结尾。除SETS,ENDSETS,D…

数据结构——“二叉搜索树”

二叉搜索树是一个很重要的数据结构&#xff0c;它的特殊结构可以在很短的时间复杂度找到我们想要的数据。最坏情况下的时间复杂度是O(n)&#xff0c;最好是O(logn)。接下来看一看它的接口函数的实现。 为了使用方便&#xff0c;这里采用模版的方式&#xff1a; 一、节点 temp…

【监控】【Nginx】使用 Docker 部署 Prometheus + Grafana 监控 Nginx

在现代应用程序中&#xff0c;监控是确保服务高可用性和性能的关键。本文将详细介绍如何使用 Docker 部署 Prometheus 和 Grafana&#xff0c;以监控 Nginx。我们将分步骤讲解每个环节&#xff0c;以确保你能够顺利完成整个过程。 准备工作 在开始之前&#xff0c;请确保你的…

Redis详细解析

Redis 什么是Redis?关系型与非关系型数据库Redis可以做什么Redis入门安装在Windows系统上安装在Linux系统上安装 Redis在Linux系统上启动运行如何设置redis-server后台运行与关闭如何设置redis客户端登录时需要验证密码**设置允许远程连接redis服务**Redis数据类型Redis常用命…

帝可得项目总结

业务需求 在区域列表查询中&#xff0c;需要显示每个区域的点位数 (1)同步存储:在区域表中有点位数的字段&#xff08;冗余字段6.&#xff09;&#xff0c;当点位发生变化时&#xff0c;同步区域表中的点位数。 优点:由于是单表查询操作&#xff0c;查询列表效率最高。 缺点…