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

news2025/4/21 15:37:31

一、目的:介绍一下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>
                        <TextBlock
                            Grid.Row="0"
                            Grid.RowSpan="2"
                            Grid.Column="5"
                            Margin="1"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch"
                            Background="White"
                            Text="LineGrid" />

                        <Label
                            Margin="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>
                        <TextBlock
                            Grid.Row="0"
                            Grid.RowSpan="2"
                            Grid.Column="5"
                            Margin="1"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch"
                            Background="White"
                            Text="LineGrid" />

                        <Label
                            Margin="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>
                <TextBlock
                    Grid.Row="0"
                    Grid.RowSpan="2"
                    Grid.Column="5"
                    Margin="1"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch"
                    Background="White"
                    Text="LineGrid" />

                <Label
                    Margin="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>
                        <TextBlock
                            Grid.Row="0"
                            Grid.RowSpan="2"
                            Grid.Column="5"
                            Margin="1"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch"
                            Background="White"
                            Text="LineGrid" />

                        <Label
                            Margin="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.coloradmin.cn/o/2146413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#实战|大乐透选号器[11]:确认选号功能的实现

哈喽,你好啊,我是雷工! 接着练习大乐透选号器的功能,这里练习实现确认选号功能; 以下为实现笔记; 01 效果演示 实现点击确认选号,将机选或手动选出的号码,添加到列表中显示; 02 设置DataGridView 首先设置控件GataGridView的属性; 2.1、编辑列 选中控件,点击右上角的…

最新Kali Linux超详细安装教程(附镜像包)

一、镜像下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1BfiyAMW6E1u9fhfyv8oH5Q 提取码&#xff1a;tft5 二、配置虚拟机 这里我们以最新的vm17.5为例。进行配置 1.创建新的虚拟机&#xff1a;选择自定义 2.下一步 3.选择稍后安装操作系统 4.选择Debian版本 因…

AI绘画实操 Stable Diffusion 到底怎么玩儿,新手必看的AI绘画入门安装使用教程

大家好&#xff0c;我是灵魂画师向阳 2024年&#xff0c;是AI绘画技术飞速发展的一年&#xff0c;各种AI绘画工具层出不穷&#xff0c;为了让大家在了解和学习AI绘画的过程中少走弯路&#xff0c;今天我将详细介绍目前世界上使用用户最多&#xff0c;社区最大&#xff0c;生态…

Springboot与minio

一、介绍 Minio是一个简单易用的云存储服务&#xff0c;它让你可以轻松地把文件上传到互联网上&#xff0c;这样无论你在哪里&#xff0c;只要有网络&#xff0c;就能访问或分享这些文件。如果你想要从这个仓库里取出一张图片或一段视频&#xff0c;让网站的访客能看到或者下载…

遭华尔街大幅看好,收入高速增长但面临困境,Zillow股票还能买入吗?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经的核心观点&#xff1a; &#xff08;1&#xff09;Wedbush已经将Zillow的评级上调为“跑赢大盘”&#xff0c;目标价为80美元。 &#xff08;2&#xff09;第二季度业绩强劲&#xff0c;收入继续保持着两位数增长…

esp32-C2 对接火山引擎实现语音转文本(二)

目录 一、 语音转文本初始化 二、 WedStream 事件处理函数 一、 语音转文本初始化 Volcengine_vtt_handle_t Volcengine_Vtt_Init(Volcengine_vtt_config_t *config) {// 管道配置audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();Volcengine_vtt_t *vt…

架构师:在 Spring Cloud 中实现全局异常处理的技术指南

1、简述 在分布式系统中,微服务架构是最流行的设计模式之一。Spring Cloud 提供了各种工具和库来简化微服务的开发和管理。然而,随着服务的增多,处理每个服务中的异常变得尤为复杂。因此,实现统一的全局异常处理成为了关键。本篇博客将介绍如何在 Spring Cloud 微服务架构…

DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?

日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData)&#xff0c;在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。 P.S&#xff1a;DevExpress WinForms拥有180…

关于github GPG的配置

GitHub 使用 OpenPGP 库来确认本地签名的提交和标记&#xff0c;是否根据你在 GitHub.com 上添加到帐户的公钥进行加密验证。 这里是github关于GPG密钥的文档&#xff1a;https://docs.github.com/zh/authentication/managing-commit-signature-verification/about-commit-sig…

开放式耳机和骨传导耳机哪个好用?全面解析哪个品牌的开放式蓝牙耳机质量好

当谈到开放式耳机与骨传导耳机之间的选择时&#xff0c;两种类型的耳机各有千秋&#xff0c;适合不同的使用场景和个人偏好。 开放式耳机的设计让耳朵可以自由呼吸&#xff0c;同时让部分环境音进入&#xff0c;这样用户可以在享受音乐的同时保持对外界的感知&#xff0c;非常…

求Huffman树及其matlab程序详解

#################本文为学习《图论算法及其MATLAB实现》的学习笔记################# 算法用途 求Haffman树 算法思想 根据定理4.17,给出求Huffman树的算法步骤如下: ①对给出的所要求的叶子顶点的权进行从小到大排序,写出的权重向量 ; ②根据定理4.17,写出兄弟的权重分别为…

9月19日微语报,星期四,农历八月十七

9月19日微语报&#xff0c;星期四&#xff0c;农历八月十七&#xff0c;工作愉快&#xff0c;生活喜乐&#xff01; 一份微语报&#xff0c;众览天下事&#xff01; 1、台风“普拉桑”将影响东海&#xff0c;自然资源部启动海洋灾害三级应急响应。 2、国家体育总局&#xff…

Spring6梳理9—— 依赖注入之注入对象类型属性

9.1 依赖注入之外部注入对象类型属性 9.1.1 创建dept与emp类 1.dept类 package com.atguigu.spring6.iocxml.ditest;//部门类 public class Dept {private String dname;public String getDname() {return dname;}public void setDname(String dname) {this.dname dname;…

强化雨天巡检,智能巡检机器人确保变电站安全运行

中央气象台9月19日6时继续发布暴雨黄色预警&#xff1a;预计&#xff0c;9月19日8时至20日8时&#xff0c;内蒙古中部、河北北部、安徽东南部、江苏南部、上海、浙江大部、海南岛以及青海东北部、甘肃西南部、辽宁中部、福建西北部、江西中部等地部分地区有大到暴雨&#xff0c…

Linux系统编程入门 | 模拟实现 ls -l 命令

模拟实现代码 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <string.h>int main(int argc, char* argv[]) {if (a…

Sidewalk介绍

目录 1 前言2 简介2.1 注意事项 3 结束语 1 前言 Sidewalk是Amazon出的一个针对IoT物联网的协议&#xff0c;类似于LoRaWAN协议&#xff0c;针对小而美的低功耗设备。Amazon Sidewalk支持低带宽和远程连接&#xff0c;使用BLE进行短距离通信&#xff0c;使用900MHz的频率的LoR…

Selenium实现滑动滑块验证码验证!

背景&#xff1a;在部分的登录中有滑动验证码的验证&#xff0c;由于滑动验证码的缺块是随机的就导致实现起来比较困难&#xff01; 01、实现方案 模板匹配 通过openCV分析两个图片的相似度&#xff0c;获取两个相似度很高图片的坐标&#xff0c;从而计算两个图片的距离。 轮…

(k8s)Kubernetes部署Promehteus

转载&#xff1a;Kubernetes&#xff08;k8s&#xff09;部署Promehteus 一、概述 在1.8版本以后heapster由metrics-server替代&#xff1b;从k8s的v1.11版本开始已经全面转向以Prometheus为核心的新监控体系架构&#xff1b;kube-prometheus 中包含了 prometheus 监控所用到的…

Sui Builder House锦集,原生USDC和CCTP即将登陆Sui

在9月17日新加坡Sui Builder House活动上&#xff0c;我们度过了充满知识分享和社区建设的精彩一天&#xff01;感谢数百位参会的开发者&#xff0c;一同庆祝Sui社区&#xff0c;并了解最新的动态&#xff01; 在过去的24小时内&#xff0c;发布了以下重要消息&#xff0c;不容…

C语言 | Leetcode C语言题解之第416题分割等和子集

题目&#xff1a; 题解&#xff1a; bool canPartition(int* nums, int numsSize) {if (numsSize < 2) {return false;}int sum 0, maxNum 0;for (int i 0; i < numsSize; i) {sum nums[i];maxNum fmax(maxNum, nums[i]);}if (sum & 1) {return false;}int tar…