WPF Grid 绘制网格线

时间:2021-07-14
本文章向大家介绍WPF Grid 绘制网格线,主要包括WPF Grid 绘制网格线使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

WPF Grid 中 有一个ShowGridLines, 通常这个只用于测试、设计等场合,而且是虚线,无法定制,本文参考ShowGridLines的实现方式,添加了两个依赖属性,可以自行定制网格线,并控制其显示行为。


1 public class TestGrid : Grid 2 { 3 public static DependencyProperty ShowGridBordersProperty = DependencyProperty.Register(nameof(ShowGridBorders), typeof(bool), typeof(TestGrid ), new PropertyMetadata(ShowGridBordersChanged)); 4 public static DependencyProperty GridBorderPenProperty = DependencyProperty.Register(nameof(GridBorderPen), typeof(Pen), typeof(TestGrid), new PropertyMetadata(GridBorderPenChanged)); 5 private GridBordersRenderer _gridBordersRenderer; 6 /// <summary> 7 /// 显示边框笔线 8 /// </summary> 9 public bool ShowGridBorders 10 { 11 get 12 { 13 return (bool)GetValue(ShowGridBordersProperty); 14 } 15 set 16 { 17 SetValue(ShowGridBordersProperty, value); 18 } 19 } 20 /// <summary> 21 /// Grid 边框笔线 22 /// </summary> 23 public Pen GridBorderPen 24 { 25 get 26 { 27 return (Pen)GetValue(GridBorderPenProperty); 28 } 29 set 30 { 31 SetValue(GridBorderPenProperty, value); 32 } 33 } 34 35 protected override int VisualChildrenCount => base.VisualChildrenCount + (_gridBordersRenderer != null ? 1 : 0); 36 37 protected override Visual GetVisualChild(int index) 38 { 39 if (index == base.VisualChildrenCount) 40 { 41 if (_gridBordersRenderer == null) 42 { 43 throw new ArgumentOutOfRangeException("index", index, "超出索引范围"); 44 } 45 return _gridBordersRenderer; 46 } 47 return base.GetVisualChild(index); 48 } 49 protected override Size ArrangeOverride(Size arrangeSize) 50 { 51 Size size = base.ArrangeOverride(arrangeSize); 52 GridBordersRenderer gridBordersRenderer = EnsureGridBordersRenderer(); 53 if (gridBordersRenderer != null) 54 { 55 gridBordersRenderer.UpdateRenderBounds(size); 56 } 57 return size; 58 } 59 60 private GridBordersRenderer EnsureGridBordersRenderer() 61 { 62 if (ShowGridBorders && _gridBordersRenderer == null) 63 { 64 _gridBordersRenderer = new GridBordersRenderer(); 65 _gridBordersRenderer.BorderPen = GridBorderPen; 66 AddVisualChild(_gridBordersRenderer); 67 } 68 if (!ShowGridBorders && _gridBordersRenderer != null) 69 { 70 RemoveVisualChild(_gridBordersRenderer); 71 _gridBordersRenderer = null; 72 } 73 return _gridBordersRenderer; 74 } 75 private static void ShowGridBordersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 76 { 77 Grid grid = d as Grid; 78 grid.InvalidateVisual(); 79 } 80 81 private static void GridBorderPenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 82 { 83 TestGrid grid = d as TestGrid; 84 if (grid._gridBordersRenderer != null) 85 { 86 grid._gridBordersRenderer.BorderPen = (Pen)e.NewValue; 87 grid.InvalidateVisual(); 88 } 89 } 90 91 class GridBordersRenderer : DrawingVisual 92 { 93 private Pen borderPenField; 94 public Pen BorderPen 95 { 96 get 97 { 98 if (borderPenField == null) 99 { 100 borderPenField = new Pen(Brushes.Gray, 0.1); 101 borderPenField.StartLineCap = PenLineCap.Square; 102 borderPenField.EndLineCap = PenLineCap.Square; 103 } 104 return borderPenField; 105 } 106 set 107 { 108 borderPenField = value; 109 } 110 } 111 public void UpdateRenderBounds(Size boundsSize) 112 { 113 using (DrawingContext drawingContext = RenderOpen()) 114 { 115 TestGrid grid = VisualTreeHelper.GetParent(this) as TestGrid; 116 if (grid != null && grid.ShowGridBorders) 117 { 118 var rowDefinitions = DefinitionsU(grid); 119 for (int i = 1; i < rowDefinitions.Length; i++) 120 { 121 double xOffset = FinalOffset(rowDefinitions[i]); 122 DrawGridLine(drawingContext, xOffset, 0.0, xOffset, boundsSize.Height); 123 } 124 var columnDefinitions = DefinitionsV(grid); 125 for (int j = 1; j < columnDefinitions.Length; j++) 126 { 127 double yOffset = FinalOffset(columnDefinitions[j]); 128 DrawGridLine(drawingContext, 0.0, yOffset, boundsSize.Width, yOffset); 129 } 130 DrawGridRectangle(drawingContext, 0.0, 0.0, boundsSize.Width, boundsSize.Height); 131 } 132 } 133 } 134 135 private void DrawGridLine(DrawingContext drawingContext, double startX, double startY, double endX, double endY) 136 { 137 Point point = new Point(startX, startY); 138 Point point2 = new Point(endX, endY); 139 drawingContext.DrawLine(BorderPen, point, point2); 140 } 141 142 private void DrawGridRectangle(DrawingContext drawingContext, double startX, double startY, double endX, double endY) 143 { 144 Rect rect = Rect.Parse($"{startX},{startY},{endX},{endY}"); 145 drawingContext.DrawRectangle(null, BorderPen, rect); 146 } 147 148 private DefinitionBase[] DefinitionsU(Grid grid) 149 { 150 DefinitionBase[] definitions = (DefinitionBase[])typeof(Grid).InvokeMember("DefinitionsU", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, Type.DefaultBinder, grid, null); 151 return definitions; 152 } 153 154 private DefinitionBase[] DefinitionsV(Grid grid) 155 { 156 DefinitionBase[] definitions = (DefinitionBase[])typeof(Grid).InvokeMember("DefinitionsV", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, Type.DefaultBinder, grid, null); 157 return definitions; 158 } 159 private double FinalOffset(DefinitionBase definition) 160 { 161 return (double)definition.GetType().InvokeMember("FinalOffset", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, Type.DefaultBinder, definition, null); 162 } 163 } 164 }

 第一篇文章,多余话不太会说,看代码吧。

原文地址:https://www.cnblogs.com/FengKaKa/p/15010495.html