You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM DataGrid:根据选中行值设置单元格背景色

解决WPF DataGrid选中行后动态对比单元格背景色问题

场景概述

开发WPF应用收集不同版本设备的设置(单设备约500项,设置数量/内容随版本增减),使用Dictionary<string, string>存储单设备设置,转换为DataTable绑定到DataGrid实现可视化。需求:选中某行后,其他行同列单元格值与选中行相同则显示绿色背景,不同则显示红色背景,切换选中行时自动更新背景色。

解决方案

1. 优化ViewModel选中行数据获取逻辑

原CellSelected方法循环SelectedCells效率较低,利用SelectionUnit="FullRow"的特性,直接获取选中的DataRowView并转换为Dictionary:

private void CellSelected(object o)
{
    DataGrid dataGrid = o as DataGrid;
    if (dataGrid?.SelectedItem is DataRowView selectedRowView)
    {
        var newSelectedUnit = selectedRowView.Row.Table.Columns
            .Cast<DataColumn>()
            .ToDictionary(col => col.ColumnName, col => selectedRowView.Row[col].ToString());
        SelectedUnit = newSelectedUnit;
    }
}

2. 实现MultiValueConverter处理背景色逻辑

创建转换器,接收三个参数:当前单元格值、选中行对应列的值、当前行是否选中,根据对比结果返回对应背景色:

using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfApp1
{
    public class CellBackgroundConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length != 3) return Brushes.Transparent;

            bool isCurrentRowSelected = (bool)values[2];
            if (isCurrentRowSelected)
            {
                return Brushes.Blue; // 选中行保持蓝色背景
            }

            string cellValue = values[0]?.ToString() ?? "-";
            string selectedValue = values[1]?.ToString() ?? "-";

            return cellValue.Equals(selectedValue, StringComparison.Ordinal) ? Brushes.Green : Brushes.Red;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

3. 修改DataGrid的CellStyle绑定逻辑

通过MultiBinding将所需参数传递给转换器,替换原有的静态触发器:

<DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
        <Setter Property="Background">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource CellBackgroundConverter}">
                    <!-- 当前单元格的值 -->
                    <Binding Path="Content.Text" RelativeSource="{RelativeSource Self}" />
                    <!-- 选中行对应列的值:通过列头名称从SelectedUnit字典中获取 -->
                    <Binding Path="DataContext.SelectedUnit[{Binding Path=Column.Header, RelativeSource={RelativeSource Self}}]" 
                             RelativeSource="{RelativeSource AncestorType=DataGrid}" />
                    <!-- 当前行是否被选中 -->
                    <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=DataGridRow}" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
        <!-- 可选:增强选中行的视觉效果 -->
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="BorderBrush" Value="Black" />
                <Setter Property="BorderThickness" Value="2" />
            </Trigger>
        </Style.Triggers>
    </Style>
</DataGrid.CellStyle>

关键说明

  • 转换器中统一处理null值为"-",与ViewModel中缺失设置的填充逻辑保持一致,避免对比异常
  • MultiBinding仅在三个绑定值(单元格值、选中行数据、行选中状态)变化时触发转换,减少不必要的计算
  • 选中行保持蓝色背景,未选中行根据值对比结果显示绿/红,完全匹配需求

内容的提问来源于stack exchange,提问作者nilsakesson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:19:54