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

如何给已绑定数据库数据的WPF DataGrid添加自定义列及值?

问题解决与自定义列实现方案

先解决No.列空白问题

你的SQL查询仅获取了scenarioName和scenarioDate,但XAML绑定的scenarioID字段并不在查询结果里,DataTable自然没有这个数据,导致列空白。修改SQL语句,把scenarioID加入查询即可:

string sql = "SELECT scenarioID, scenarioName, scenarioDate FROM tbl_scenario";

重新填充DataTable后,scenarioID字段会存在,绑定就能正常显示序号。


添加自定义列(含非数据库来源列)

下面提供两种常用实现方式,按需选择:

方式一:直接扩展DataTable(快速实现)

无需额外实体类,直接给DataTable新增列并赋值,适合小型场景:

// 填充DataTable后添加自定义列
DataTable dtScenario = new DataTable();
sqlDataAdapter.Fill(dtScenario);

// 1. 添加计算值列(比如根据日期判断状态)
dtScenario.Columns.Add("Status", typeof(string));
foreach (DataRow row in dtScenario.Rows)
{
    DateTime date = Convert.ToDateTime(row["scenarioDate"]);
    row["Status"] = date < DateTime.Today ? "已过期" : "正常";
}

// 2. 添加固定标识列(用于后续XAML中的操作按钮)
dtScenario.Columns.Add("Action", typeof(string));
foreach (DataRow row in dtScenario.Rows)
{
    row["Action"] = "操作";
}

// 重新绑定
scenarioDataGrid.ItemsSource = dtScenario.DefaultView;

对应的XAML列定义:

<DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding scenarioID}" Header="No." Width="50" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding scenarioName}" Header="场景名称" Width="150" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding scenarioDate}" Header="创建日期" Width="120" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding Status}" Header="状态" Width="80" IsReadOnly="True"/>
    <!-- 自定义操作列(用TemplateColumn放按钮) -->
    <DataGridTemplateColumn Header="操作" Width="80">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Button Content="编辑" Click="EditScenario_Click"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

方式二:使用实体类(推荐WPF开发模式)

这种方式更符合WPF的MVVM思想,便于维护和扩展,适合中大型项目:

  1. 创建包含数据库字段和自定义属性的实体类:
public class Scenario
{
    public int ScenarioID { get; set; }
    public string ScenarioName { get; set; }
    public DateTime ScenarioDate { get; set; }
    // 自定义计算属性(非数据库来源)
    public string Status => ScenarioDate < DateTime.Today ? "已过期" : "正常";
    // 自定义固定属性
    public string ButtonText => "编辑";
}
  1. 从数据库读取数据并转换为实体类列表:
List<Scenario> scenarioList = new List<Scenario>();
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT scenarioID, scenarioName, scenarioDate FROM tbl_scenario", conn))
{
    SqlDataReader reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        scenarioList.Add(new Scenario
        {
            ScenarioID = reader.GetInt32(0),
            ScenarioName = reader.GetString(1),
            ScenarioDate = reader.GetDateTime(2)
        });
    }
}
conn.Close();
// 直接绑定实体列表
scenarioDataGrid.ItemsSource = scenarioList;
  1. XAML绑定实体属性:
<DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding ScenarioID}" Header="No." Width="50" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding ScenarioName}" Header="场景名称" Width="150" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding ScenarioDate}" Header="创建日期" Width="120" IsReadOnly="True"/>
    <DataGridTextColumn Binding="{Binding Status}" Header="状态" Width="80" IsReadOnly="True"/>
    <DataGridTemplateColumn Header="操作" Width="80">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Button Content="{Binding ButtonText}" Click="EditScenario_Click"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

额外需求:显示行号(不依赖数据库ID)

如果不需要数据库的scenarioID,只想显示DataGrid的行序号,可以通过LoadingRow事件实现:

private void scenarioDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    // 行号从1开始计数
    e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}

XAML开启行头显示:

<DataGrid x:Name="scenarioDataGrid" LoadingRow="scenarioDataGrid_LoadingRow" HeadersVisibility="All">

内容的提问来源于stack exchange,提问作者Xue Xian Heah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:30:53