使用绑定进行WPF DataGrid格式化的指南
目录
介绍
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;
- 在Windows.Resource中定义CollectionViewSource
- 需要注意的是,您必须设置CollectionViewType。如果您不这样做,GridView则将使用BindingListCollectionView,它不支持排序。当然,MSDN不会在任何地方解释这一点。
- 设定DataGrid的DataContext到CollectionViewSource。
- 在后面的代码中,找到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();}
}
注意
- 只能将某些属性设置为DataGridRow,例如Background颜色。其他属性,如Fonts,在DataGridCell中被设定,即TextBlock。
- 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格式化的指南相关推荐
- WPF DataGrid:解决排序、ScrollIntoView、刷新和焦点问题
目录 介绍 第一种方法:记住选定的行,刷新DataGrid,再次选择行 最终方法:使用OneWay绑定,避免调用Refresh() 改进1:使ScrollIntoView()起作用 改进2:将选定的行 ...
- wpf DataGrid主从表,DataGrid嵌套DataGrid主从结构rowdetailtemplate实现,绑定DataTable数据源,使用Visual Studio 2017
wpf DataGrid主从表,DataGrid嵌套DataGrid主从结构rowdetailtemplate实现,绑定DataTable数据源,使用Visual Studio 2017 . 子表绑定 ...
- WPF DataGrid 如何将被选中行带到视野中
WPF DataGrid 如何将被选中行带到视野中 目录 前言 准备工作 方法一 方法二 总结 独立观察员 2021 年 12 月 11 日 前言 在 WPF 开发中,显示表格一般使用 DataGri ...
- WPF DataGrid 通过自定义表头模拟首行固定
WPF DataGrid 通过自定义表头模拟首行固定 独立观察员 2021 年 9 月 25 日 最近工作中要在 WPF 中做个表格,自然首选就是 DataGrid 控件了.问题是,UI 设计的表格是 ...
- C# WPF DataGrid控件的详细介绍和推荐一些样式设计
前面介绍过使用DataGrid简单绑定一个数据模型,接着介绍DataGrid的一些详细操作. 参考:C# WPF DataGrid的使用 定制DataGrid控件基本外观属性 RowBackgroun ...
- WPF DataGrid 和LINQ to SQL示例程序之一 (提供源代码下载)
WPF DataGrid 和LINQ to SQL示例程序之一 (提供源代码下载) WPF DataGrid 系列示例程序,由浅入深逐步介绍如何在WPF 应用程序中使用新的DataGrid 控件.本篇 ...
- WPF DataGrid 主从表 数据绑定方式
昨天在网上搜了一下午没有看到一个关于WPF DataGrid主从表数据绑定的示例,但是我坚信这个简单的功能肯定是支持的,经研究问题解决. 现把相关方法共享下,给现在还在郁闷的兄弟们一点参考.重点在于定 ...
- WPF DataGrid控件的使用
WPF DataGrid控件的使用 下面以一个例子说明DataGrid控件的使用方法: 一.程序框架 使用了MVVM Light框架 二.主要代码部分(使用MVVM Light框架): 1.主窗体xa ...
- 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 ...
最新文章
- ajax 使用 JSONP 时,只能 GET 不能 POST
- 教你Mac电脑复制手机粘贴的隐藏玩法
- 信息学奥赛一本通 1080:余数相同问题 | OpenJudge NOI 小学奥数/2.1 7647:余数相同问题
- 平面设计python教程_什么是平面设计? - Python学习教程的个人空间 - OSCHINA - 中文开源技术交流社区...
- 【Hadoop】伪分布式安装---MapReduce程序运行到YARN上,编写MapReduce程序---HDFS yarn
- sql server 2005下开启xp_cmdshell的办法
- BZOJ 2039 人员雇佣 (最小割)
- js学习笔记 chapter5 引用类型
- 2T以上的盘怎么分区, 利用parted创建 linuxTB硬盘GPT分区
- sublime改成中文简体及菜单变成中文
- 如何选购电风扇,一本电风扇选购攻略都在这里!
- sql优化之b+树锁引实战
- startx 命令详解
- 线段树1——神奇的数据结构
- 总有一条适合你|程序猿的女朋友
- “Cache-主存”和“主存和辅存”的区别
- Fiddler抓包6-打断点(bpu)
- 联考事业单位计算机类面试,2018年5.26事业单位联考E类常见面试题(下)
- 绝对值编码器工作原理是什么?单圈/多圈绝对值编码器有何区别?
- Python---数据分析---绘制条形图---横竖条形图
热门文章
- docker kali安装mysql_Linux环境使用Docker安装MySql
- python etree详解_使用lxml.etree解析python alexa结果
- spring3.0 aop 获取 ibatis 执行的语句_Mybatis 源码分析:执行器
- bytes数组转string指定编码_好程序员Java学习路线分享Java基础之string
- visual2019没有勾选的在如何加入_没有预留期权池,如何激励新加入者?
- 洒脱书法!值得学习的帅气高级手写字体设计
- 建议电商美工收藏的素材网站
- python在法律中的应用_Python在共轭梯度法中的运用
- C语言为四维数组申请动态内存空间的方法(二)
- Linux系统利用C语言获取网口信息(IP地址,MAC地址,状态,带宽speed等)