WPF 数据网格。无法突出显示自定义样式的单元格
Posted
技术标签:
【中文标题】WPF 数据网格。无法突出显示自定义样式的单元格【英文标题】:WPF datagrid. Cannot highlight custom styled cell 【发布时间】:2017-09-05 14:53:59 【问题描述】:我有一个数据网格,它是一个财务计算器,其中一些单元格在负值时变为红色。这是通过带有转换器的 DataTrigger 完成的。我也有覆盖系统突出显示选择颜色。我现在的问题是,当我选择一行时,红色单元格不会突出显示。
Here's the picture
据我了解,自定义单元格样式会覆盖选择。我希望我的自定义红色单元格也用 0.5 不透明度的蓝色条突出显示。我该如何解决这个问题?
好吧,我可以为单元格样式添加一个额外的触发器,该触发器会在选择时更改 BG 颜色并调整颜色以使其适合,但这相当麻烦。或者也许我可以在这里以某种方式实现具有不透明度的叠加颜色?
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue" />
</Trigger>
以下是完整代码。这是一个精简、重量轻但功能齐全的示例。
XAML
<Window.Resources>
<local:ValueToBoolConverter x:Key="ValueToBoolConverter"/>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="Binding MainTable"
AutoGenerateColumns="False"
CanUserAddRows="False">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="Azure"/>
<Style.Resources>
<SolidColorBrush x:Key="x:Static SystemColors.HighlightBrushKey" Color="Blue" Opacity="0.5" />
<SolidColorBrush x:Key="x:Static SystemColors.HighlightTextBrushKey" Color="Black" />
<SolidColorBrush x:Key="x:Static SystemColors.InactiveSelectionHighlightBrushKey" Color="Transparent" />
</Style.Resources>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Income Day" Binding="Binding IncomeDay" />
<DataGridTextColumn Header="Income Week" Binding="Binding IncomeWeek">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="Binding IncomeWeek, Converter=StaticResource ValueToBoolConverter" Value="true">
<Setter Property="Background" Value="Salmon"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Income Month" Binding="Binding IncomeMonth" />
<DataGridTextColumn Header="Income Year" Binding="Binding IncomeYear" Width="*" />
</DataGrid.Columns>
</DataGrid>
</Grid>
C#
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Datagrid_Cell_Highlight
public class TableData
public decimal IncomeDay get; set;
public decimal IncomeWeek get; set;
public decimal IncomeMonth get; set;
public decimal IncomeYear get; set;
public class ViewModel
public ObservableCollection<TableData> MainTable get; set;
public ViewModel()
MainTable = new ObservableCollection<TableData>
new TableData IncomeDay = (decimal)1.11 ,
new TableData IncomeDay = (decimal)2.22 ,
new TableData IncomeDay = (decimal)-1.23 ,
new TableData IncomeDay = (decimal)-2.34
;
foreach (var table in MainTable)
table.IncomeWeek = table.IncomeDay * 7;
table.IncomeMonth = table.IncomeDay * 30;
table.IncomeYear = table.IncomeDay * 365;
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
DataContext = new ViewModel();
public class ValueToBoolConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
if ((value is decimal) && ((decimal)value < 0))
return true;
else return false;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotImplementedException();
【问题讨论】:
【参考方案1】:“Kludge”与否,单元格的 Background
确实会“覆盖”行的背景,因此您应该在单元格样式中添加另一个触发器以考虑到这一点。例如,您可以使用包含红色和蓝色画笔的 MultiDataTrigger
和 DrawingBrush
:
<DataGridTextColumn Header="Income Week" Binding="Binding IncomeWeek">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="Binding IncomeWeek, Converter=StaticResource ValueToBoolConverter" Value="true">
<Setter Property="Background" Value="Salmon"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="Binding IncomeWeek, Converter=StaticResource ValueToBoolConverter" Value="true" />
<Condition Binding="Binding IsSelected, RelativeSource=RelativeSource Self" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Background">
<Setter.Value>
<DrawingBrush Viewport="0,0,1,1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<SolidColorBrush Color="Salmon"/>
</GeometryDrawing.Brush>
</GeometryDrawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<SolidColorBrush Color="Blue" Opacity="0.2"/>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
【讨论】:
正是我需要的。接受。【参考方案2】:您可以使用 MultiDataTrigger 实现此目的。但为什么你认为这是一个“杂牌”?我认为它相当优雅。
mm8 代码的替代方法是简单地设置两个 MultiDataTrigger。第一种在 IsSelected 为 false 时触发,第二种在 IsSelected 为 true 时触发。
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="Binding RelativeSource=RelativeSource Self, Path=IsSelected" Value="False"/>
<Condition Binding="Binding IncomeWeek, Converter=StaticResource ValueToBoolConverter" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Salmon"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="Binding RelativeSource=RelativeSource Self, Path=IsSelected" Value="True"/>
<Condition Binding="Binding IncomeWeek, Converter=StaticResource ValueToBoolConverter" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="DynamicResource x:Static SystemColors.HighlightBrushKey"/>
<Setter Property="BorderThickness" Value="0"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
【讨论】:
这行得通,赞成,但我接受了 mm8 的回答,因为他实现了不透明性。至于“kludge”,我看不到一种简单的方法可以将这种方法用于多个列。但这可能是另一个问题。以上是关于WPF 数据网格。无法突出显示自定义样式的单元格的主要内容,如果未能解决你的问题,请参考以下文章
Excel设置表格样式的显示效果使用excel如何改变表格样式
当在顶部添加新帖子时,UICollectionView 单元格自定义 FlowLayout 中断