WPF---ListView添加窗格线
来源:互联网 发布:怎样成为淘宝卖家 编辑:程序博客网 时间:2024/05/16 18:51
要想直接在WPF中给ListView加上横竖线条,是一件很费劲的事情,不过我们可以通过其他的办法,来绕过去,具体是什么办法呢,就看下面的步骤吧!
1. 建立一个WPF程序
2. 添加一个类文件,命名为GridLineDecorator.cs,写入如下内容
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Markup;using System.Windows.Media;using System.Windows.Threading;namespace ListViewWithLines{ [ContentProperty("Target")] public class GridLineDecorator : FrameworkElement { private ListView _target; private DrawingVisual _gridLinesVisual = new DrawingVisual(); private GridViewHeaderRowPresenter _headerRowPresenter = null; public GridLineDecorator() { this.AddVisualChild(_gridLinesVisual); this.AddHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler(OnScrollChanged)); } #region GridLineBrush /// <summary> /// GridLineBrush Dependency Property /// </summary> public static readonly DependencyProperty GridLineBrushProperty = DependencyProperty.Register("GridLineBrush", typeof(Brush), typeof(GridLineDecorator), new FrameworkPropertyMetadata(Brushes.LightGray, new PropertyChangedCallback(OnGridLineBrushChanged))); /// <summary> /// Gets or sets the GridLineBrush property. This dependency property /// indicates .... /// </summary> public Brush GridLineBrush { get { return (Brush)GetValue(GridLineBrushProperty); } set { SetValue(GridLineBrushProperty, value); } } /// <summary> /// Handles changes to the GridLineBrush property. /// </summary> private static void OnGridLineBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((GridLineDecorator)d).OnGridLineBrushChanged(e); } /// <summary> /// Provides derived classes an opportunity to handle changes to the GridLineBrush property. /// </summary> protected virtual void OnGridLineBrushChanged(DependencyPropertyChangedEventArgs e) { DrawGridLines(); } #endregion #region Target public ListView Target { get { return _target; } set { if (_target != value) { if (_target != null) Detach(); RemoveVisualChild(_target); RemoveLogicalChild(_target); _target = value; AddVisualChild(_target); AddLogicalChild(_target); if (_target != null) Attach(); InvalidateMeasure(); } } } private void GetGridViewHeaderPresenter() { if (Target == null) { _headerRowPresenter = null; return; } _headerRowPresenter = Target.GetDesendentChild<GridViewHeaderRowPresenter>(); } #endregion #region DrawGridLines private void DrawGridLines() { if (Target == null) return; if (_headerRowPresenter == null) return; var itemCount = Target.Items.Count; if (itemCount == 0) return; var gridView = Target.View as GridView; if (gridView == null) return; // 获取drawingContext var drawingContext = _gridLinesVisual.RenderOpen(); var startPoint = new Point(0, 0); // 为了对齐到像素的计算参数,否则就会看到有些线是模糊的 var dpiFactor = this.GetDpiFactor(); var pen = new Pen(this.GridLineBrush, 1 * dpiFactor); var halfPenWidth = pen.Thickness / 2; var guidelines = new GuidelineSet(); // 计算表头的偏移量和大小 var headerOffset = _headerRowPresenter.TranslatePoint(startPoint, this); var headerSize = _headerRowPresenter.RenderSize; var headerBottomY = headerOffset.Y + headerSize.Height; // 计算ScrollViewer的可视区域大小 var item0 = _target.ItemContainerGenerator.ContainerFromIndex(0); if (item0 == null) return; var scrollViewer = item0.GetAncestor<ScrollViewer>(); if (scrollViewer == null) return; var contentElement = scrollViewer.Content as UIElement; var maxLineX = scrollViewer.ViewportWidth; var maxLineY = headerBottomY + contentElement.RenderSize.Height; var vLineY = 0.0; // 画横线 for (int i = 0; i < itemCount; i++) { var item = Target.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem; if (item != null) { var renderSize = item.RenderSize; var offset = item.TranslatePoint(startPoint, this); var hLineX1 = offset.X; var hLineX2 = offset.X + renderSize.Width; var hLineY = offset.Y + renderSize.Height; vLineY = hLineY; // 小于视图起始位置的不绘制 if (hLineY <= headerBottomY) continue; // 大于视图结束位置之后的不绘制 if (hLineY > maxLineY) break; // 如果大于横向宽度,取横向宽度 if (hLineX2 > maxLineX) hLineX2 = maxLineX; // 加入参考线,对齐到像素 guidelines.GuidelinesY.Add(hLineY + halfPenWidth); drawingContext.PushGuidelineSet(guidelines); drawingContext.DrawLine(pen, new Point(hLineX1, hLineY), new Point(hLineX2, hLineY)); drawingContext.Pop(); } } // 画竖线 var columns = gridView.Columns; var vLineX = headerOffset.X; if (vLineY > maxLineY) vLineY = maxLineY; foreach (var column in columns) { var columnWidth = column.GetColumnWidth(); vLineX += columnWidth; if (vLineX > maxLineX) break; // 加入参考线,对齐到像素 guidelines.GuidelinesX.Add(vLineX + halfPenWidth); drawingContext.PushGuidelineSet(guidelines); drawingContext.DrawLine(pen, new Point(vLineX, headerBottomY), new Point(vLineX, vLineY)); drawingContext.Pop(); } drawingContext.Close(); } #endregion #region Overrides to show Target and grid lines protected override int VisualChildrenCount { get { return Target == null ? 1 : 2; } } protected override System.Collections.IEnumerator LogicalChildren { get { yield return Target; } } protected override Visual GetVisualChild(int index) { if (index == 0) return _target; if (index == 1) return _gridLinesVisual; throw new IndexOutOfRangeException(string.Format("Index of visual child '{0}' is out of range", index)); } protected override Size MeasureOverride(Size availableSize) { if (Target != null) { Target.Measure(availableSize); return Target.DesiredSize; } return base.MeasureOverride(availableSize); } protected override Size ArrangeOverride(Size finalSize) { if (Target != null) Target.Arrange(new Rect(new Point(0, 0), finalSize)); return base.ArrangeOverride(finalSize); } #endregion #region Handle Events private void Attach() { _target.Loaded += OnTargetLoaded; _target.Unloaded += OnTargetUnloaded; _target.SizeChanged += OnTargetSizeChanged; } private void Detach() { _target.Loaded -= OnTargetLoaded; _target.Unloaded -= OnTargetUnloaded; _target.SizeChanged -= OnTargetSizeChanged; } private void OnTargetLoaded(object sender, RoutedEventArgs e) { if (_headerRowPresenter == null) GetGridViewHeaderPresenter(); DrawGridLines(); } private void OnTargetUnloaded(object sender, RoutedEventArgs e) { DrawGridLines(); } private void OnTargetSizeChanged(object sender, SizeChangedEventArgs e) { DrawGridLines(); } private void OnScrollChanged(object sender, RoutedEventArgs e) { DrawGridLines(); } #endregion }}
3. 添加一个类文件,命名为GridViewColumnHelper.cs,写入如下内容
using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Windows.Controls;namespace ListViewWithLines{ internal static class GridViewColumnHelper { private static PropertyInfo DesiredWidthProperty = typeof(GridViewColumn).GetProperty("DesiredWidth", BindingFlags.NonPublic | BindingFlags.Instance); public static double GetColumnWidth(this GridViewColumn column) { return (double.IsNaN(column.Width)) ? (double)DesiredWidthProperty.GetValue(column, null) : column.Width; } }}
4. 添加一个类文件,命名为VisualService.cs,写入如下内容
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Media;using System.Windows;namespace ListViewWithLines{ public static class VisualService { public static double GetDpiFactor(this Visual target) { var source = PresentationSource.FromVisual(target); return source == null ? 1.0 : 1 / source.CompositionTarget.TransformToDevice.M11; } public static T GetAncestor<T>(this DependencyObject target) where T : DependencyObject { var parent = VisualTreeHelper.GetParent(target); if (parent is T) return (T)parent; if (parent != null) return parent.GetAncestor<T>(); return null; } public static T GetDesendentChild<T>(this DependencyObject target) where T : DependencyObject { var childCount = VisualTreeHelper.GetChildrenCount(target); if (childCount == 0) return null; for (int i = 0; i < childCount; i++) { var current = VisualTreeHelper.GetChild(target, i); if (current is T) return (T)current; var desendent = current.GetDesendentChild<T>(); if (desendent != null) return desendent; } return null; } }}
5. 在界面主XAML文件中,加入以下内容
<Windowxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"x:Class="TreeViewDesign.MainWindow"xmlns:l="clr-namespace:ListViewWithLines"x:Name="Window"Title="开发测试工具"Width="900" Height="600" Background="White" WindowState="Maximized"> <Grid> <l:GridLineDecorator GridLineBrush="{Binding ElementName=cb_GridLineBrush, Path=SelectedItem.Content}"> <ListView Background="White" FocusVisualStyle="{x:Null}" Name="FileInfo"> <ListView.View> <GridView> <GridViewColumn Header="工程路径" Width="600" DisplayMemberBinding="{Binding XPath=@PATH}"/> <GridViewColumn Header="修改日期" Width="200" DisplayMemberBinding="{Binding XPath=@MODIFY}"/> </GridView> </ListView.View> <ListView.ContextMenu> <ContextMenu Name="ContextMenu"> <MenuItem Header="创建工程" /> <MenuItem Header="添加工程" /> <MenuItem Header="打开工程" /> <MenuItem Header="删除工程" /> </ContextMenu> </ListView.ContextMenu> </ListView> </l:GridLineDecorator> </Grid></window>
6. 在界面主XAML文件对应的cs文件的构造函数中,加入以下内容
public MainWindow(){ this.InitializeComponent(); // 在此点下面插入创建对象所需的代码。 string xmlpath = Directory.GetCurrentDirectory() + "\\context.xml"; XmlDocument xml = new XmlDocument(); xml.Load(xmlpath); XmlDataProvider xdp = new XmlDataProvider(); xdp.Document = xml; xdp.XPath = @"/Context/URInfo"; this.FileInfo.DataContext = xdp; this.FileInfo.SetBinding(ComboBox.ItemsSourceProperty, new Binding());}
7. 自己建立一个xml文件,里面填上相应的数据(有几列就写几列)
8. 编译WPF程序,大功告成了!
- WPF---ListView添加窗格线
- wpf中listview添加排序
- WPF 用c#代码实现listview添加控件ProgressBar
- WPF对ListView的ListViewItem添加双击事件
- WPF ListView
- WPF listview中添加ProgressBar并实现UI的实时响应
- WPF中为ListView动态绑定数据且添加一列复选框
- WPF 获取ListView中列添加LinkButton按钮,点击按钮的当前行的ID值
- [.Net码农][WPF] ListView 中 View 的模板替换(添加/删除列)
- WPF-ListView选中行
- wpf中ListView排序
- WPF LISTVIEW 排序
- wpf listview 使用
- wpf listview 使用
- WPF ListView 隔行不同颜色
- WPF,ListView设置分组
- WPF ListView 居中显示
- WPF ListView VisualPanel
- 2012-02-18 09:55 android信息提示框与对话框 转载的,看着方便
- IE 浏览器的创新
- python 面向对象入门 - 之 单元测试
- paip.activex控件在WEB中使用流程与工具
- JAVA实现Excel导入/导出【转】
- WPF---ListView添加窗格线
- Xcode 4 常用快捷键
- RTMP协议详解(转)
- python中读写文件及中文编码处理方法
- Android 对话框基本应用详细教程
- 如何计算某天是星期几
- UML类图几种关系的总结
- python读文本后如何去行文的\n
- poj 3295