我有一个数据网格,它是一个财务计算器,其中一些单元格在负值时变为红色。这是通过带转换器的数据触发器完成的。我还覆盖了系统突出显示选择颜色。我现在的问题是,当我选择一行时,红色单元格不会突出显示。
这是图片
据我了解,自定义单元格样式会覆盖选择。我希望我的自定义红色单元格也用 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();
}
}
}
"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>
您可以使用MultiDataTrigger来实现此目的。但是为什么你认为这是一个"笨蛋"?我认为它相当优雅。
mm8代码的替代方案是简单地设置两个多数据触发器。当 IsSelected 为假时触发的第一种方式,当 IsSelected 为真时触发的第一种方式。
<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>