1.思路主要代码

wpf的gridline原本效果是虚线类型的。有时候需要设计成表格形式的,因此有了用附加属性来自动绘制边框线的想法。

思路:绘制Line并添加到grid的children里,但效果并不理想,会出现锯齿,像素对齐,模糊等问题。

UseLayoutRounding="False"
SnapsToDevicePixels="True"

RenderOptions.EdgeModeProperty 貌似都没起作用。

于是想到了用border来实现,简单又实用吧 哈哈。

大致思路如下:绘制border的左边框和上边框,在边界的时候考虑边界封闭。然后将border平移一半的距离。这样边框就居中并且包围了所有的线。

主要代码如下:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media; namespace 用附加属性修改Grid的边框
{
public class GridHelper
{
private static void RefreshGrid(Grid grid, int lineWidth, Brush color)
{
for (var i = grid.Children.Count - 1; i > 0; i--)
{
var child = grid.Children[i]; var bd = child as Border;
if (bd != null && bd.Tag != null && bd.Tag.ToString() == "gridline")
{
grid.Children.Remove(bd);
}
}
var rows = grid.RowDefinitions.Count;
var cols = grid.ColumnDefinitions.Count;
//边界考虑
if (rows == 0)
{
rows = 1;
}
if (cols == 0)
{
cols = 1;
}
//生成行列
for (var i = 0; i < rows; i++)
{
for (var j = 0; j < cols; j++)
{
var thick = new Thickness(lineWidth, lineWidth, 0, 0);
var margin = new Thickness(-lineWidth/2d, -lineWidth/2d, 0, 0);
//边界考虑
if (i == 0)
{
margin.Top = 0;
}
if (i == rows - 1)
{
thick.Bottom = lineWidth;
}
if (j == 0)
{
margin.Left = 0;
}
if (j == cols - 1)
{
thick.Right = lineWidth;
}
var bd = new Border
{
BorderThickness = thick,
Margin = margin,
BorderBrush = color,
Tag = "gridline"
};
Grid.SetRow(bd, i);
Grid.SetColumn(bd, j);
grid.Children.Add(bd);
}
}
grid.InvalidateArrange();
grid.InvalidateVisual();
} #region 线颜色 // Using a DependencyProperty as the backing store for LineColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty LineColorProperty =
DependencyProperty.RegisterAttached("LineColor", typeof (Brush), typeof (GridHelper),
new PropertyMetadata(Brushes.Black, LineColorPropertyChanged)); public static Brush GetLineColor(DependencyObject obj)
{
return (Brush) obj.GetValue(LineColorProperty);
} public static void SetLineColor(DependencyObject obj, Brush value)
{
obj.SetValue(LineColorProperty, value);
} private static void LineColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = d as Grid;
if (grid == null)
{
return;
}
var showLines = GetShowGridLines(grid);
var color = GetLineColor(grid);
var lineWidth = GetLineWidth(grid);
if (showLines)
{
// grid.SnapsToDevicePixels = true;
grid.Loaded += delegate { RefreshGrid(grid, lineWidth, color); };
}
} #endregion #region 线宽度 // Using a DependencyProperty as the backing store for LineWidth. This enables animation, styling, binding, etc...
public static readonly DependencyProperty LineWidthProperty =
DependencyProperty.RegisterAttached("LineWidth", typeof (int), typeof (GridHelper),
new PropertyMetadata(1, LineWidthPropertyChanged)); public static int GetLineWidth(DependencyObject obj)
{
return (int) obj.GetValue(LineWidthProperty)
;
} public static void SetLineWidth(DependencyObject obj, int value)
{
obj.SetValue(LineWidthProperty, value);
} private static void LineWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = d as Grid;
if (grid == null)
{
return;
}
var showLines = GetShowGridLines(grid);
var color = GetLineColor(grid);
var lineWidth = GetLineWidth(grid);
if (showLines)
{
// grid.SnapsToDevicePixels = true;
grid.Loaded += delegate { RefreshGrid(grid, lineWidth, color); };
}
} #endregion #region 是否显示线 // Using a DependencyProperty as the backing store for ShowGridLines. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ShowGridLinesProperty =
DependencyProperty.RegisterAttached("ShowGridLines", typeof (bool), typeof (GridHelper),
new PropertyMetadata(false, ShowGridLinesPropertyChanged)); public static bool GetShowGridLines(DependencyObject obj)
{
return (bool) obj.GetValue(ShowGridLinesProperty);
} public static void SetShowGridLines(DependencyObject obj, bool value)
{
obj.SetValue(ShowGridLinesProperty, value);
} private static void ShowGridLinesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = d as Grid;
if (grid == null)
{
return;
}
var showLines = GetShowGridLines(grid);
var color = GetLineColor(grid);
var lineWidth = GetLineWidth(grid);
if (showLines)
{
// grid.SnapsToDevicePixels = true;
grid.Loaded += delegate { RefreshGrid(grid, lineWidth, color); };
}
} #endregion
}
}

  

2.效果图

效果还可以,任何分辨率下,任何边框大小,都没有出现像素对齐或者模糊问题。 图中的虚线是grid的默认gridLine,红色和绿色是自定义的gridline,跟虚线完美重合。

3.源码下载

https://files.cnblogs.com/files/chlm/%E7%94%A8%E9%99%84%E5%8A%A0%E5%B1%9E%E6%80%A7%E4%BF%AE%E6%94%B9Grid%E7%9A%84%E8%BE%B9%E6%A1%86.rar

WPF利用附加属性修改ShowGridLines效果的更多相关文章

  1. WPF中利用RadialGradient模拟放大镜效果

    原文:WPF中利用RadialGradient模拟放大镜效果 --------------------------------------------------------------------- ...

  2. WPF Adorner+附加属性 实现控件友好提示

    标题太空泛,直接上图 无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成. 例如WPF自带的控件上要加这样的效 ...

  3. 利用Photoshop修改图片以达到投稿要求

    摘自:http://www.dxy.cn/bbs/thread/8602152#8602152 利用Photoshop修改图片以达到投稿要求 软件版本为Photoshop CS V8.0.1(中文版) ...

  4. WPF利用动画实现圆形进度条

    原文:WPF利用动画实现圆形进度条 这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到 ...

  5. WPF 图片浏览 伪3D效果

    原文:WPF 图片浏览 伪3D效果 首先上效果图: 因项目要求,需要把图片以"好看"."炫"的效果展示出来,特地研究了一下WPF关于3D方面的制作,奈何最终成果 ...

  6. 【WPF】两则动画效果

    原文:[WPF]两则动画效果 引言 利用WPF的动画可以轻而易举的实现各种各样的特效,如擦除,滑动进入等,先看两个效果图 第一个效果 这个动画其实利用了OpacityMask和LinearGradie ...

  7. WPF利用HelixToolKit后台导入3D模型

    原文:WPF利用HelixToolKit后台导入3D模型 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/de ...

  8. 用WPF轻松打造iTunes CoverFlow效果

    原文:用WPF轻松打造iTunes CoverFlow效果 用WPF轻松打造iTunes CoverFlow效果                                             ...

  9. c# wpf 利用截屏键实现截屏功能

    原文:c# wpf 利用截屏键实现截屏功能     最近做一个wpf程序需要截图功能,查找资料费了一些曲折,跟大家分享一下.     先是找到了这样一份代码:     static class Scr ...

随机推荐

  1. BAT脚本/Dos 改ip地址

    BAT脚本/Dos 改ip 经常换地方上网,总改这些很麻烦,直接写三个bat,点一下就换了.需要管理员权限.之前用python的wmi写过,但是没起作用. ip:10.10.41.15 子网掩码:25 ...

  2. Java线程中断机制-如何中断线程

    介绍: 对于线程一共分为五个状态:新建状态,就绪状态,阻塞状态,运行状态,死亡状态,有时候把阻塞状态又分为同步阻塞和等待阻塞. 有时想让主线程启动的一个子线程结束运行,我们就需要让这个子线程中断,不再 ...

  3. java基础学习系列二

    循环语句 1,for(){} 2,while(){} 3,do{}while() continue和break用法 break是结束循环 continue结束本次循环

  4. Django——ORM

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  5. shior笔记

    Shiro 是一个强大而灵活的开源安全框架,能够非常清晰的处理认证.授权.管理会话以及密码加密.如下是它所具有的特点: 易于理解的 Java Security API: 简单的身份认证(登录),支持多 ...

  6. JS常见操作,日期操作,字符串操作,表单验证等

    复制代码 //第一篇博文,希望大家多多支持 /***** BasePage.js 公共的 脚本文件 部分方法需引用jquery库 *****/ //#region 日期操作 //字符串转化为时间. f ...

  7. 笔试常考--浏览器兼容性问题及解决方案(CSS)

    问题一:不同浏览器的标签默认的外补丁和内补丁不同 问题现象:随便写几个标签,不加样式控制的情况下,各自的margin 和padding差异较大. 解决方案:css里加: ;;} 备注:这个是最常见的也 ...

  8. java多线程的(一)-之java线程的使用

    一.摘要 每天都和电脑打交道,也相信大家使用过资源管理器杀掉过进程.而windows本身就是多进程的操作系统 在这里我们理解两组基本概念: 1.进程和线程的区别???? 2.并行与并发的区别???? ...

  9. bash下常用快捷键

    Ctrl-A 相当于HOME键,用于将光标定位到本行最前面Ctrl-E 相当于End键,即将光标移动到本行末尾Ctrl-B 相当于左箭头键,用于将光标向左移动一格Ctrl-F 相当于右箭头键,用于将光 ...

  10. JavaScript(第二十五天)【事件绑定及深入】

    事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型).现代事件绑定在传统绑定上提供了更强大更方便的功能.   一.传统事件绑定的问题 传统事件绑定有内联模型 ...