WPF数据网格。无法突出显示自定义样式的单元格

时间:2017-04-10 13:59:49

标签: wpf datagrid styles cell highlight

我有一个数据网格,它是一个金融计算器,其中一些单元格在负值上变为红色。这是通过带转换器的DataTrigger完成的。我也覆盖了系统高亮选择颜色。我现在的问题是,当我选择一行时,红色单元格不会突出显示。

Here's the picture

据我所知,自定义单元格样式会覆盖选择。我希望我的自定义红色单元格也用0.5不透明蓝色条突出显示。我该如何解决这个问题?

好吧,我可以为细胞样式添加一个额外的触发器,在选择时改变BG颜色并调整颜色以适应,但这相当于一个kludge。或者也许我可以在某种程度上实现不透明度的叠加颜色?

<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();
        }
    }
}

2 个答案:

答案 0 :(得分:0)

“Kludge”与否,单元格的Background确实会“覆盖”该行的背景,因此您应该将另一个触发器添加到考虑到这一点的单元格样式中。例如,您可以使用包含红色和蓝色画笔的MultiDataTriggerDrawingBrush

<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>

答案 1 :(得分:0)

您可以使用MultiDataTrigger实现此目的。但是你为什么认为这是一个&#34; kludge&#34;?我觉得它很优雅。

mm8代码的替代方法是简单地设置两个MultiDataTriggers。 IsSelected为false时触发的第一个为Is,而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>