WPF如何利用附加属性修改ShowGridLines效果详解

前言

附加属性是说一个属性本来不属于某个对象,但由于某种需求而被后来附加上,也就是把对象放入一个特定环境后对象才具有的属性就称为附加属性,附加属性的作用就是将属性与数据类型解耦,让数据类型的设计更加灵活,举例,一个TextBox被放在不同的布局容器中时就会有不同的布局属性,这些属性就是由布局容器为TextBox附加上的,附加属性的本质就是依赖属性,二者仅仅在注册和包装器上有一点区别

小技巧,在VS中输入propa后,连按两次tab键,可以添加好一个附加属性的框架,继续按tab键,可以继续修改附加属性的内容

本文主要介绍的是关于WPF用附加属性修改ShowGridLines效果的相关内容,下面话不多说了,来一起看看详细的介绍吧。

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.源码下载

下载地址:http://xiazai.jb51.net/201804/yuanma/WPF-fujia-ShowGridLines(jb51.net).rar

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • WPF如何利用附加属性修改ShowGridLines效果详解

    前言 附加属性是说一个属性本来不属于某个对象,但由于某种需求而被后来附加上,也就是把对象放入一个特定环境后对象才具有的属性就称为附加属性,附加属性的作用就是将属性与数据类型解耦,让数据类型的设计更加灵活,举例,一个TextBox被放在不同的布局容器中时就会有不同的布局属性,这些属性就是由布局容器为TextBox附加上的,附加属性的本质就是依赖属性,二者仅仅在注册和包装器上有一点区别 小技巧,在VS中输入propa后,连按两次tab键,可以添加好一个附加属性的框架,继续按tab键,可以继续修改附加

  • Flutter利用Canvas绘制精美表盘效果详解

    目录 前言 初始化 面板 刻度 刻度线 刻度值 指针 时针 分针 秒针 动起来 前言 趁着周末空闲时间使用 Flutter 的 Canvas制作了一个精美表盘. 最终实现的效果还不错,如下: 前面说到使用 Canvas 实现该表盘效果,而在 Flutter 中使用 Canvas 更多的则是继承 CustomPainter 类实现 paint 方法,然后在 CustomPaint 中使用自定义实现的 CustomPainter. 比如这里创建的 DialPainter 使用如下: @overrid

  • 利用Matlab制作环形相册效果详解

    目录 运行效果 完整步骤 1.图片准备及导入 2.为每张图片制作遮罩层 3.调整每张图大小 4.绘图及绘图参数详解 完整代码 运行效果 完整步骤 1.图片准备及导入 要制作一款相册足够的图片量是必不可少的,不然整个相册只有一张图来回重复多没意思呀,因此我们需要一个文件夹专门放图片,为了方便导入,这里全部都是jpg格式: 图片导入代码: path='.\album\';%文件夹路径 files=dir(fullfile(path,'*.jpg')); picNum=size(files,1); %

  • WPF实现雷达扫描图的绘制详解

    目录 前言 制作思路 具体实现 前言 实现一个雷达扫描图. 源代码在TK_King/雷达 (gitee.com),自行下载就好了 制作思路 绘制圆形(或者称之轮) 绘制分割线 绘制扫描范围 添加扫描点 具体实现 首先我们使用自定义的控件.你可以使用vs自动添加,也可以手动创建类.注意手动创建时要创建Themes/Generic.xaml的文件路径哦. 控件继承自itemscontrol,取名叫做Radar. 我们第一步思考如何实现圆形或者轮,特别是等距的轮. 我们可以使用简单的itemscont

  • 微信小程序点击控件修改样式实例详解

    微信小程序点击控件修改样式实例详解 现在要在微信小程序中实现点击控件修改样式,如下: 微信小程序中不支持直接操作dom,要实现这种效果,我们需要通过设置data,然后利用数据和界面的双向绑定来实现它. 第一步:在wxss中定义被点击和未被点击的样式,如下: .service_selection .is_checked{ border: 1px solid #FE0002 ; color: #FE0002 ; background: #fff; } .service_selection .norm

  • JavaScript实现六种网页图片轮播效果详解

    目录 1.当鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮. 2.动态生成小圆圈 3.点击小圆圈,小圆圈变色 4.点击小圆圈滚动图片 5.点击右侧按钮一次,就让图片滚动一张. 6.点击右侧按钮, 小圆圈跟随变化 7.左侧按钮功能制作 8.自动播放功能 在网页中,我们经常会看到各种轮播图的效果,它们到底是怎样实现的呢?今天,我们就一起来看一下!首先,我们需要准备若干张图片,在这里我准备了五张图片. 功能需求: 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮. 点击右侧按钮一次,图片往左播放

  • Python利用随机函数生成变化图形详解

    鉴于上一篇中最后三个问题: 1.上述程序是否能进行优化(比如功能相同的) 2.创建三个3个实例,用了3个语句,能否建一个函数,只输入一个数n,就自动创建n个实例?同时,每个实例的num_times随机,(n比较大时,num_times应该比较小) 3.当实现上述功能后,程序运行,只输入一个参数(创建实例的个数),就会自动生成对应的num_times,并分别调用相关函数生成对应图表. 可以,在类Rand_moving()中计算每一步的方向和移动位置时,都用到了一个乘法公式, x_direction

  • Python利用随机函数生成变化图形详解(一)

    目录 前言 一.rand_moving.py文件定义功能如下 二.绘图模块 小结 前言 综合前述的类.函数.matplotlib等,完成一个随机移动的过程(注意要确定移动的次数,比如10万次),每次行走都完全是随机的,没有明确的方向,结果是由一系列随机决策确定的,最后显示出每次移动的位置的图表. 思考: 1)每次走动多少个像素,由随机函数决定,每次移动方向也随机确定.由随机方向和随机像素共同移动位置大小和方向. 2)保证将每次移动的位置保存在列表中,供后面matplotlib调用,生成图表. 故

  • 利用Python还原方阵游戏详解

    目录 一.前言 二.游戏规则 三.numpy模块 四.第一步:大循环and获取规格 五.第二步:初始化棋盘 六.第三步:标注矩阵功能(难) 七.第四步:查看标注矩阵功能 八.第五步:胜利侦测 九.第六步:查看行列信息(难) 十.第七步:重新开始功能 十一.得分与完善and完整代码 一.前言 写这篇文章的灵感来源于我玩游戏的时候(为了避免过不了审就不说是啥游戏了),看见一个大佬在游戏里面建造了“还原方阵游戏”,就感觉很牛掰,就想着python不是有矩阵吗,可不可以还原一下呢? 说干就干,我写的那个

  • MySQL数据库设计之利用Python操作Schema方法详解

    弓在箭要射出之前,低声对箭说道,"你的自由是我的".Schema如箭,弓似Python,选择Python,是Schema最大的自由.而自由应是一个能使自己变得更好的机会. Schema是什么? 不管我们做什么应用,只要和用户输入打交道,就有一个原则--永远不要相信用户的输入数据.意味着我们要对用户输入进行严格的验证,web开发时一般输入数据都以JSON形式发送到后端API,API要对输入数据做验证.一般我都是加很多判断,各种if,导致代码很丑陋,能不能有一种方式比较优雅的验证用户数据呢

随机推荐