如何通过XAML样式触发器更改DataGrid当前单元格对应列头背景
问题说明
点击DataGridCell或当前单元格发生变更时,原有实现通过后置代码监听DataGrid的CurrentCellChanged事件,修改当前单元格所属列的列头背景,对应后置代码实现如下:
private void DataGrid_CurrentCellChanged(object sender, EventArgs e) { foreach (var item in dataGrid.Columns) { if (item.HeaderStyle != null) { item.HeaderStyle = null; } } Style selectedColumnStyle = new Style(typeof(DataGridColumnHeader)); selectedColumnStyle.Setters.Add(new Setter(DataGridColumnHeader.BackgroundProperty, Brushes.Gray)); dataGrid.Columns[Index].HeaderStyle = selectedColumnStyle; }
需求为仅使用XAML编写样式与触发器,实现与上述后置代码完全一致的功能。
实现方案
无需编写任何事件处理的后置业务代码,通过XAML样式搭配触发器即可实现完全一致的效果,核心逻辑是通过数据触发器监听DataGrid当前选中单元格的列归属,自动匹配更新对应列头样式。
- 项目中添加一个通用的相等判断多值转换器即可,属于通用工具类,不耦合具体业务逻辑:
using System.Globalization; using System.Windows.Data; public class EqualityConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { return values.Length >= 2 && Equals(values[0], values[1]); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }
- 在XAML资源中注册转换器,再编写
DataGridColumnHeader的目标样式即可,样式可以直接写在目标DataGrid的资源字典中,也可以放在全局资源对所有DataGrid生效:
<!-- 注册转换器,注意替换local为当前项目对应的CLR命名空间前缀 --> <local:EqualityConverter x:Key="IsCurrentColumnConverter" /> <Style TargetType="DataGridColumnHeader"> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource IsCurrentColumnConverter}"> <!-- 绑定到所属DataGrid当前选中单元格对应的列对象 --> <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=DataGrid}" Path="CurrentCell.Column"/> <!-- 绑定到当前列头自身关联的列对象 --> <Binding RelativeSource="{RelativeSource Self}" Path="Column"/> </MultiBinding> </DataTrigger.Binding> <!-- 匹配成功时设置列头灰色背景,和原后置代码效果一致 --> <Setter Property="Background" Value="Gray"/> </DataTrigger> </Style.Triggers> </Style>
方案说明
- 该方案完全通过样式驱动,不需要给DataGrid手动挂载任何事件监听
- 当DataGrid的当前单元格变更时,触发器会自动完成列匹配和样式更新,未命中触发器的列头会自动恢复默认样式,不需要手动遍历所有列重置样式
- 实现效果和原有后置代码完全一致,且更易复用,所有应用该样式的DataGrid都会自动获得选中列高亮效果
内容的提问来源于stack exchange,提问作者Ravi Joshi
相关产品推荐
相关产品推荐

