引言
在与DataGrid相关的项目中,会有一个比较常见的需求.那就是在根据数据设置行的样式,例如行的背景色或者字体色.我们用到的方法有几个,下面一个个说来.
准备工作
介绍方法之前,先定义数据类,是一个比较简单的分数表,有姓名,分数等,代码如下:
public class Score { public string Name { get; set; } public int Chinese { get; set; } public int Math { get; set; } }
再创建个实例给datagrid赋值数据源,如下:
this.datagrid.ItemsSource = new List<Score> { new Score { Name = "小红", Chinese = 90, Math = 80 }, new Score { Name = "小明", Chinese = 60, Math = 90 }, new Score { Name = "小李", Chinese = 95, Math = 58 }, new Score { Name = "小雷", Chinese = 50, Math = 80 }};
1.数据触发器
最简单最方便的方法就是定义一个DataTrigger,但是缺点也很明显,只能用于单个数据绑定和判断数据是否相等的情况.例如,我们要将语文成绩等于90的数据背景色设置为绿色,代码如下
<Style > <Style.Triggers> <DataTrigger Binding="{Binding Chinese}" Value="90"> <Setter Property="DataGridRow.Background" Value="Green"></Setter> </DataTrigger> </Style.Triggers> </Style>
2.值转换器
IValueConverter也只能应用于单数据绑定,但是它功能上强大些.例如我们要将语文成绩小于60的数据背景色设置为红色,代码如下:
定义BlackgroundConverter,如下:
public class BlackgroundConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (int.Parse(value.ToString(), NumberStyles.Any) < 60) { return new SolidColorBrush(Colors.Red ); } else { return DependencyProperty.UnsetValue; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DependencyProperty.UnsetValue; } }
定义资源
<local:BlackgroundConverter x:Key="blackgroudconverter"></local:BlackgroundConverter>
应用转换器
<Style > <Setter Property="DataGridRow.Background" Value="{Binding Chinese,Converter={StaticResource blackgroudconverter}}"></Setter> </Style>
另外,还有一个更强大的值转换器IMultiValueConverter,同时绑定语文和数学成绩,可以将语文成绩大于数学成绩的数据设置为红色,如下:
public class BlackgroudMultiConver : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { try { int one = int.Parse(values[0].ToString(), NumberStyles.Any) ; int two = int.Parse(values[1].ToString(), NumberStyles.Any); if (values[0] != null && values[1] != null && one > two) { return new SolidColorBrush(Colors.Red); } else { return DependencyProperty.UnsetValue; } } catch (Exception e) { return DependencyProperty.UnsetValue; } } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { return null; } }
3.样式选择器
从功能上看,StyleSelector是上面两个的集大成者.它可以实现多个数据值的判断和应用多个属性的设置.例如,我们可以将语文成绩大于数学成绩的数据设置为红色,字体颜色设置为蓝色,代码如下:
public class DataGridStyleSelector : StyleSelector { public override Style SelectStyle(object item, DependencyObject container) { if (item is Score) { Score tmp = (Score)item; if (tmp.Chinese > tmp.Math) { return style; } else { return null; } } else { return null; } } public Style style { get; set; } }
定义资源
<local:DataGridStyleSelector x:Key="dataGridStyleSelector"> <local:DataGridStyleSelector.style> <Style> <Setter Property="DataGridRow.Background" Value="Red"></Setter> <Setter Property="DataGridRow.Foreground" Value="Blue"></Setter> </Style> </local:DataGridStyleSelector.style> </local:DataGridStyleSelector>
应用样式选择器
<DataGrid Name="datagrid" AutoGenerateColumns="False" RowStyleSelector="{StaticResource dataGridStyleSelector}" >
但是,样式选择器也有个不如意的地方,当我们动态编辑数据的时候,不能自动引发样式的改变.这种情况没有优雅的解决方法,只能在数据变化的时候,粗暴地将对应的样式选择器设置null再设置回来.
4.乱入:模板选择器
DataTemplateSelector同样功能很强大,它可以完全改变数据的显示方式.可惜的是,datagrid没有RowTemplateSelector.只有CellTemplateSelector,我们可以利用CellTemplateSelector对单元格做点有趣的显示,例如添加点额外的文字描述,如下
public class CellDataTemplateSelector : DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { if (item is Score) { Score tmp = (Score)item; if (tmp.Chinese >=60) { return template1; } else { return template2; } } else { return null; } } public DataTemplate template1 { get; set; } public DataTemplate template2 { get; set; } }
定义资源
<local:CellDataTemplateSelector x:Key="celldatatemplateselector"> <local:CellDataTemplateSelector.template1> <DataTemplate> <TextBlock Foreground="Green" Text="{Binding Chinese,StringFormat=成绩不错:{0}}"></TextBlock> </DataTemplate> </local:CellDataTemplateSelector.template1> <local:CellDataTemplateSelector.template2> <DataTemplate> <TextBlock Foreground="Red" Text="{Binding Chinese,StringFormat=还要努力:{0}}"></TextBlock> </DataTemplate> </local:CellDataTemplateSelector.template2> </local:CellDataTemplateSelector>
应用模板选择器
<DataGridTemplateColumn CellTemplateSelector="{StaticResource celldatatemplateselector}" Header="语文分数"> </DataGridTemplateColumn>
同样,它有着和样式选择器同样的缺点.
小结
本文从简单到复杂介绍数据触发器,值转换器,样式选择器,模板选择器,它们有各自的应用场景,也有各自的局限性,在使用上要注意一下.最后,如果你有更好的建议,请不吝指教!