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

C# WPF:如何将重复DataGrid列样式转为资源并单次绑定对象?

解决方案:复用DataGrid列样式,消除重复代码

核心思路:通过BindingProxy传递列索引,让通用样式动态绑定对应Aps对象

WPF的DataGridCell上下文是行数据,无法直接获取列索引,因此需要借助**绑定代理(BindingProxy)**传递列的索引信息,让通用样式能根据索引动态绑定Aps集合里的对应项。


步骤1:实现BindingProxy类

这个类用于在资源中传递绑定值(此处为列索引):

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get => GetValue(DataProperty);
        set => SetValue(DataProperty, value);
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

步骤2:定义通用样式资源

在Resources中统一编写单元格样式和文本块样式,通过BindingProxy动态获取列索引:

<Window.Resources>
    <!-- 通用单元格样式 -->
    <Style x:Key="GenericDataGridCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource dgc}">
        <Setter Property="ToolTip" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].ToolTipText}" />
        <Setter Property="ContextMenu" Value="{StaticResource contextMenu}" />
        <Setter Property="Background" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellBackground}" />
        <Setter Property="Foreground" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellForeground}" />
        <Setter Property="BorderBrush" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellBorderBrush}" />
        <Setter Property="BorderThickness" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellBorderThickness}" />

        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellBackground}" />
                <Setter Property="Foreground" Value="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellForeground}" />
            </Trigger>
        </Style.Triggers>
    </Style>

    <!-- 通用文本块样式 -->
    <Style x:Key="GenericTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource tb}" />
</Window.Resources>

步骤3:简化DataGrid列定义

每个列只需指定索引、Header和绑定,直接引用通用样式即可:

<materialDesign:DataGridTextColumn x:Name="Jan" Header="Jan" Binding="{Binding Aps[0].CellValue}">
    <materialDesign:DataGridTextColumn.Resources>
        <!-- 当前列专属的索引代理 -->
        <local:BindingProxy x:Key="ColumnIndexProxy" Data="0"/>
    </materialDesign:DataGridTextColumn.Resources>
    <DataGridTextColumn.CellStyle>
        <StaticResource ResourceKey="GenericDataGridCellStyle"/>
    </DataGridTextColumn.CellStyle>
    <DataGridTextColumn.ElementStyle>
        <StaticResource ResourceKey="GenericTextBlockStyle"/>
    </DataGridTextColumn.ElementStyle>
</materialDesign:DataGridTextColumn>

<materialDesign:DataGridTextColumn x:Name="Feb" Header="Feb" Binding="{Binding Aps[1].CellValue}">
    <materialDesign:DataGridTextColumn.Resources>
        <local:BindingProxy x:Key="ColumnIndexProxy" Data="1"/>
    </materialDesign:DataGridTextColumn.Resources>
    <DataGridTextColumn.CellStyle>
        <StaticResource ResourceKey="GenericDataGridCellStyle"/>
    </DataGridTextColumn.CellStyle>
    <DataGridTextColumn.ElementStyle>
        <StaticResource ResourceKey="GenericTextBlockStyle"/>
    </DataGridTextColumn.ElementStyle>
</materialDesign:DataGridTextColumn>

<!-- 剩余10列依此类推,仅修改索引、Name和Header -->

可选优化:改用DataGridTemplateColumn

如果允许替换列类型,可以把单元格内容也封装到通用模板中,进一步简化代码:

<Window.Resources>
    <!-- 通用单元格内容模板 -->
    <DataTemplate x:Key="GenericCellTemplate">
        <TextBlock Text="{Binding Aps[{Binding Data, Source={StaticResource ColumnIndexProxy}}].CellValue}" 
                   Style="{StaticResource tb}"/>
    </DataTemplate>
</Window.Resources>

<!-- 列定义示例 -->
<materialDesign:DataGridTemplateColumn x:Name="Jan" Header="Jan">
    <materialDesign:DataGridTemplateColumn.Resources>
        <local:BindingProxy x:Key="ColumnIndexProxy" Data="0"/>
    </materialDesign:DataGridTemplateColumn.Resources>
    <DataGridTemplateColumn.CellStyle>
        <StaticResource ResourceKey="GenericDataGridCellStyle"/>
    </DataGridTemplateColumn.CellStyle>
    <DataGridTemplateColumn.CellTemplate>
        <StaticResource ResourceKey="GenericCellTemplate"/>
    </DataGridTemplateColumn.CellTemplate>
</materialDesign:DataGridTemplateColumn>

关键说明

  • 绑定代理的作用是突破WPF绑定上下文限制,让单元格样式能获取到列的索引值;
  • 每个列的Resources中定义独立的ColumnIndexProxy,确保样式绑定对应索引的Aps对象;
  • 所有重复的样式逻辑集中到通用资源中,后续修改只需维护一处即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:42:47