如何根据DataGridColumn类型对齐列头文本?已用触发器但未生效
DataGrid列头对齐样式触发器失效的原因及解决方法
问题背景
需求为:让DataGridComboBoxColumn的列头文本左对齐,其余类型DataGridColumn的列头文本居中。尝试两种Style触发器实现均未生效,相关代码如下:
<Window.Resources> <Style x:Key="CustomColumnHeaderStyle1" TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="Width" Value="200"/> <Style.Triggers> <DataTrigger Binding="{Binding DataContext, RelativeSource={RelativeSource Self}}" Value="{x:Type DataGridComboBoxColumn}"> <Setter Property="HorizontalContentAlignment" Value="Left" /> </DataTrigger> </Style.Triggers> </Style> <Style x:Key="CustomColumnHeaderStyle2" TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="Width" Value="200"/> <Style.Triggers> <DataTrigger Binding="{Binding Column}" Value="{x:Type DataGridComboBoxColumn}"> <Setter Property="HorizontalContentAlignment" Value="Left" /> </DataTrigger> </Style.Triggers> </Style> <ObjectDataProvider x:Key="myEnum" MethodName="GetValues" ObjectType="{x:Type core:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type Type="local:OrderStatus"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources> <Window.DataContext> <local:ViewModel/> </Window.DataContext> <Grid> <DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource CustomColumnHeaderStyle2}"> <DataGrid.Columns> <DataGridComboBoxColumn Header="Order Status" SelectedItemBinding="{Binding Status}" ItemsSource="{Binding Source={StaticResource myEnum}}" /> <DataGridTextColumn Header="Text Column" Binding="{Binding Name}"/> </DataGrid.Columns> </DataGrid> </Grid>
失效原因分析
CustomColumnHeaderStyle1 失效原因
触发器绑定{Binding DataContext, RelativeSource={RelativeSource Self}},但DataGridColumnHeader的DataContext继承自DataGrid的DataContext(即ViewModel实例),并非当前列对象,因此无法获取列类型,触发器永远无法触发。
CustomColumnHeaderStyle2 失效原因
触发器绑定Column属性的方向是正确的,但Value="{x:Type DataGridComboBoxColumn}"是在类型对象和列实例对象之间做比较:Column是DataGridComboBoxColumn的实例,而Value是Type类型的对象,两者类型不匹配,条件永远不成立,触发器无法触发。
解决方案
方法1:使用类型转换转换器
通过转换器将列实例转换为对应的类型对象,再与目标类型比较:
- 创建类型转换转换器
using System; using System.Windows.Data; namespace YourNamespace { public class ObjectToTypeConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value?.GetType(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
- 修改XAML资源和样式
<Window.Resources> <local:ObjectToTypeConverter x:Key="ObjectToTypeConverter"/> <Style x:Key="CustomColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="Width" Value="200"/> <Style.Triggers> <DataTrigger Binding="{Binding Column, Converter={StaticResource ObjectToTypeConverter}}" Value="{x:Type DataGridComboBoxColumn}"> <Setter Property="HorizontalContentAlignment" Value="Left" /> </DataTrigger> </Style.Triggers> </Style> <ObjectDataProvider x:Key="myEnum" MethodName="GetValues" ObjectType="{x:Type core:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type Type="local:OrderStatus"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources>
- 应用样式到DataGrid
<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource CustomColumnHeaderStyle}"> <DataGrid.Columns> <DataGridComboBoxColumn Header="Order Status" SelectedItemBinding="{Binding Status}" ItemsSource="{Binding Source={StaticResource myEnum}}" /> <DataGridTextColumn Header="Text Column" Binding="{Binding Name}"/> </DataGrid.Columns> </DataGrid>
方法2:直接绑定列的类型(WPF 4.5+)
若使用WPF 4.5及以上版本,可直接通过Path访问列实例的GetType()方法,无需转换器:
<Style x:Key="CustomColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="Width" Value="200"/> <Style.Triggers> <DataTrigger Binding="{Binding Column.GetType()}" Value="{x:Type DataGridComboBoxColumn}"> <Setter Property="HorizontalContentAlignment" Value="Left" /> </DataTrigger> </Style.Triggers> </Style>
内容的提问来源于stack exchange,提问作者wpf
相关产品推荐
相关产品推荐

