目录

介绍

WPF DataGrid结构

WPF绑定基础

使用的业务数据

将DataGrid与业务数据连接

DataGrid格式

格式化列

格式化完整行

根据显示的值格式化单元格

根据业务逻辑数据格式化单元

ElementStyle与CellStyle


  • 下载示例的完整源代码-17.7 KB

介绍

根据业务逻辑数据格式化WPF DataGrid内容太困难了,特别是因为MSDN没有告诉您任何有关它的信息。我花了几周时间想办法把它弄好。让我向您展示如何做到这一点,以节省您的时间并在Internet上进行无尽的搜索。

WPF DataGrid结构

DataGrid的容器层次结构是这样的:

DataGrid DataGridRowsDataGridCellTextBlock 

DataGrid包含DataGridRow, DataGridCell包含一个精确的TextBlock,如果它是一个TextColumn并且处于读取模式(编辑模式使用一个TextBox)。当然,可视化树有点复杂:

请注意,DataGridColumn不是视觉树的一部分。DataGridColumn定义中的任何内容都将应用于该列的所有单元格。

WPF绑定基础

绑定被分配给FrameworkElement属性,该属性构成绑定的目标。

WPF需要两个源信息才能进行绑定工作:

  • 来源:提供信息的对象
  • 路径:应使用源的哪个属性

通常,Source从父容器DataContext(通常是Window本身)继承。但是DataGrid的DataContext不能被用于行和单元格的结合,因为每一行需要绑定到不同的业务逻辑对象。

DataGridColumn使用DataGridColumn.Binding属性指定要显示在单元格中的值的绑定。在DataGrid运行时,为每一个TextBlock.Text创建绑定。不幸的是,DataGrid并不支持对的任何其他TextBlock属性的绑定。如果尝试为自己的TextBlock设置样式,则绑定很可能会失败,因为它不知道要使用ItemsSource中的哪个业务对象。

使用的业务数据

业务数据示例基于一些盘点数字。库存项如下所示:

public class StockItem {public string Name { get; set; }public int Quantity { get; set; }public bool IsObsolete { get; set; }
}

样本数据:

名称

数量

已过时

很多项目

100

false

足够的物品

10

false

短缺项目

1

false

有错误的项目

-1

false

过时的物品

200

true

DataGrid与业务数据连接

甚至将DataGrid与业务数据连接起来也不是一件容易的事。基本上,CollectionViewSource用来将DataGrid和业务数据联系起来:

CollectionViewSource执行实际的数据导航、排序、过滤等

<Window.Resources><CollectionViewSource x:Key="ItemCollectionViewSource"  CollectionViewType="ListCollectionView"/>
</Window.Resources> 
<DataGridDataContext="{StaticResource ItemCollectionViewSource}"ItemsSource="{Binding}"AutoGenerateColumns="False"CanUserAddRows="False">  
//create business data
var itemList = new List<stockitem>();
itemList.Add(new StockItem {Name= "Many items",      Quantity=100, IsObsolete=false});
itemList.Add(new StockItem {Name= "Enough items",    Quantity=10,  IsObsolete=false});
...//link business data to CollectionViewSource
CollectionViewSource itemCollectionViewSource;
itemCollectionViewSource = (CollectionViewSource)(FindResource("ItemCollectionViewSource"));
itemCollectionViewSource.Source = itemList; 
  1. 在Windows.Resource中定义CollectionViewSource
  2. 需要注意的是,您必须设置CollectionViewType。如果您不这样做,GridView则将使用BindingListCollectionView,它不支持排序。当然,MSDN不会在任何地方解释这一点。
  3. 设定DataGrid的DataContext到CollectionViewSource。
  4. 在后面的代码中,找到CollectionViewSource并将您的业务数据分配给Source属性

在本文中,仅读取数据。如果用户应该能够编辑数据,请使用ObservableCollection。

DataGrid格式

格式化列

格式化整个列很容易。只需直接在DataGridColumn中设置Fontweight属性即可:

<DataGridTextColumn Binding="{Binding Path=Name}" Header="Name" FontWeight="Bold"/>

此处的绑定不涉及格式设置,但指定单元格的内容(即TextBlock的Text属性)。

格式化完整行

格式化行是特殊的,因为将有很多行。DataGrid为此提供了RowStyle属性。这种样式将适用于每一个DataGridRow。

<datagrid.rowstyle><style targettype="DataGridRow"><Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self},Path=Item.Quantity, Converter={StaticResource QuantityToBackgroundConverter}}"/></style>
</datagrid.rowstyle>

该DatGridRow有一个Item属性,它包含了该行的业务逻辑对象。因此,DataRow的绑定必须绑定到自身!该路径有点令人惊讶,因为Item是类型Object的并且不知道任何业务数据属性。但是WPF绑定应用了一些魔术,并且仍然找到了StockItem的Quantity属性。

在此示例中,行的背景取决于业务对象的Quantity属性的值。如果库存中有很多物品,则背景应为白色,如果只剩少量,则背景应为灰色。QuantityToBackgroundConverter执行必要的计算:

class QuantityToBackgroundConverter: IValueConverter {public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {if (value is int) {int quantity = (int)value;if (quantity>=100) return Brushes.White;if (quantity>=10) return Brushes.WhiteSmoke;if (quantity>=0) return Brushes.LightGray;return Brushes.White; //quantity should not be below 0}//value is not an integer. Do not throw an exception// in the converter, but return something that is obviously wrongreturn Brushes.Yellow;}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {throw new NotImplementedException();}
}  

注意

  1. 只能将某些属性设置为DataGridRow,例如Background颜色。其他属性,如Fonts,在DataGridCell中被设定,即TextBlock。
  2. DataGridCell,TextBlock等在DataGridRow上绘制。如果两者都设置为Background,则DataGridRowBackground将会被隐藏。

根据显示的值格式化单元格

仅格式化一个单元格而不是整个行是一个挑战。在文本列中,单元格具有需要设置样式的TextBlock元素。为TextBlock创建Style的操作很容易,但是如何将TextBlock属性绑定到适当的业务对象呢?DataGrid已经绑定TextBlock的Text属性。如果样式仅取决于单元格值,则可以简单地对该Text属性使用自绑定。

示例:在我们的股票表格中,该Quantity值应始终大于或等于零。如果数量为负,则为错误,应以红色显示:

<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text, Converter={StaticResource QuantityToForegroundConverter}}" /> 

根据业务逻辑数据格式化单元

最复杂的情​​况是,单元格格式不取决于单元格值,而是取决于其他一些业务数据。在我们的示例中,如果一个项目的数量已过时,则应显示为删除线。为此,需要将TextDecorations属性链接到该行的业务对象。意思是TextBlock必须找到父级DataGridRow。幸运的是,可以使用相对源来绑定到父级可视化对象:

<Window.Resources><Style x:Key="QuantityStyle" TargetType="TextBlock">...<Setter Property="TextDecorations"Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}},Path =Item.IsObsolete,Converter={StaticResource IsObsoleteToTextDecorationsConverter}}" /></Style>
</Window.Resources>
...
<DataGrid ...>...<DataGrid.Columns>...<DataGridTextColumn Binding="{Binding Path=Quantity}" Header="Quantity" ElementStyle="{StaticResource QuantityStyle}"/></DataGrid.Columns></DataGrid>

ElementStyle与CellStyle

DataGridTextColumn从DataGridBoundColumn继承,而从DataGridColumn继承。

从DataGridBoundColumn它继承属性ElementStyle。此样式将应用于TextBlock控件。

从DataGridColumn它继承属性Cell。此样式将应用于DataGridCell控件。

请注意,在上面的可视树中,DataGridCell包含一个TextBlock。DataGridCell首先被绘制,然后TextBlock在上面。

因为TextBlock和DataGridCell从Control继承,都具有背景、边框、字体、前景、填充和内容对齐的属性。意思是可以在ElementStyle或CellStyle中设置Background颜色。

什么时候应该使用?我们在这里使用ElementStyle,因为它还支持TextBlock设置诸如TextDecorations的特定属性。对于某些属性,如Background,CellStyle应被使用,因为它覆盖了所有单元格,而ElementStyle设置了仅文本块的背景,而文本块仅覆盖了单元格的一部分。

也可以同时设置两种样式。如果他们用不同的值设置相同的属性,则ElementStyle获胜。

https://www.codeproject.com/Articles/683429/Guide-to-WPF-DataGrid-Formatting-Using-Bindings

使用绑定进行WPF DataGrid格式化的指南相关推荐

  1. WPF DataGrid:解决排序、ScrollIntoView、刷新和焦点问题

    目录 介绍 第一种方法:记住选定的行,刷新DataGrid,再次选择行 最终方法:使用OneWay绑定,避免调用Refresh() 改进1:使ScrollIntoView()起作用 改进2:将选定的行 ...

  2. wpf DataGrid主从表,DataGrid嵌套DataGrid主从结构rowdetailtemplate实现,绑定DataTable数据源,使用Visual Studio 2017

    wpf DataGrid主从表,DataGrid嵌套DataGrid主从结构rowdetailtemplate实现,绑定DataTable数据源,使用Visual Studio 2017 . 子表绑定 ...

  3. WPF DataGrid 如何将被选中行带到视野中

    WPF DataGrid 如何将被选中行带到视野中 目录 前言 准备工作 方法一 方法二 总结 独立观察员 2021 年 12 月 11 日 前言 在 WPF 开发中,显示表格一般使用 DataGri ...

  4. WPF DataGrid 通过自定义表头模拟首行固定

    WPF DataGrid 通过自定义表头模拟首行固定 独立观察员 2021 年 9 月 25 日 最近工作中要在 WPF 中做个表格,自然首选就是 DataGrid 控件了.问题是,UI 设计的表格是 ...

  5. C# WPF DataGrid控件的详细介绍和推荐一些样式设计

    前面介绍过使用DataGrid简单绑定一个数据模型,接着介绍DataGrid的一些详细操作. 参考:C# WPF DataGrid的使用 定制DataGrid控件基本外观属性 RowBackgroun ...

  6. WPF DataGrid 和LINQ to SQL示例程序之一 (提供源代码下载)

    WPF DataGrid 和LINQ to SQL示例程序之一 (提供源代码下载) WPF DataGrid 系列示例程序,由浅入深逐步介绍如何在WPF 应用程序中使用新的DataGrid 控件.本篇 ...

  7. WPF DataGrid 主从表 数据绑定方式

    昨天在网上搜了一下午没有看到一个关于WPF DataGrid主从表数据绑定的示例,但是我坚信这个简单的功能肯定是支持的,经研究问题解决. 现把相关方法共享下,给现在还在郁闷的兄弟们一点参考.重点在于定 ...

  8. WPF DataGrid控件的使用

    WPF DataGrid控件的使用 下面以一个例子说明DataGrid控件的使用方法: 一.程序框架 使用了MVVM Light框架 二.主要代码部分(使用MVVM Light框架): 1.主窗体xa ...

  9. WPF Datagrid with some read-only rows - Stack Overflow

    原文:WPF Datagrid with some read-only rows - Stack Overflow up vote 21 down vote accepted I had the sa ...

最新文章

  1. ajax 使用 JSONP 时,只能 GET 不能 POST
  2. 教你Mac电脑复制手机粘贴的隐藏玩法
  3. 信息学奥赛一本通 1080:余数相同问题 | OpenJudge NOI 小学奥数/2.1 7647:余数相同问题
  4. 平面设计python教程_什么是平面设计? - Python学习教程的个人空间 - OSCHINA - 中文开源技术交流社区...
  5. 【Hadoop】伪分布式安装---MapReduce程序运行到YARN上,编写MapReduce程序---HDFS yarn
  6. sql server 2005下开启xp_cmdshell的办法
  7. BZOJ 2039 人员雇佣 (最小割)
  8. js学习笔记 chapter5 引用类型
  9. 2T以上的盘怎么分区, 利用parted创建 linuxTB硬盘GPT分区
  10. sublime改成中文简体及菜单变成中文
  11. 如何选购电风扇,一本电风扇选购攻略都在这里!
  12. sql优化之b+树锁引实战
  13. startx 命令详解
  14. 线段树1——神奇的数据结构
  15. 总有一条适合你|程序猿的女朋友
  16. “Cache-主存”和“主存和辅存”的区别
  17. Fiddler抓包6-打断点(bpu)
  18. 联考事业单位计算机类面试,2018年5.26事业单位联考E类常见面试题(下)
  19. 绝对值编码器工作原理是什么?单圈/多圈绝对值编码器有何区别?
  20. Python---数据分析---绘制条形图---横竖条形图

热门文章

  1. docker kali安装mysql_Linux环境使用Docker安装MySql
  2. python etree详解_使用lxml.etree解析python alexa结果
  3. spring3.0 aop 获取 ibatis 执行的语句_Mybatis 源码分析:执行器
  4. bytes数组转string指定编码_好程序员Java学习路线分享Java基础之string
  5. visual2019没有勾选的在如何加入_没有预留期权池,如何激励新加入者?
  6. 洒脱书法!值得学习的帅气高级手写字体设计
  7. 建议电商美工收藏的素材网站
  8. python在法律中的应用_Python在共轭梯度法中的运用
  9. C语言为四维数组申请动态内存空间的方法(二)
  10. Linux系统利用C语言获取网口信息(IP地址,MAC地址,状态,带宽speed等)