c# - 设置具有对象 DataSource 的 DataGridView 中自动生成的列的格式

标签 c# winforms datagridview .net-2.0

我想根据我的自定义类自动创建我的 DataGridView 的所有列。每件事都按其应有的方式工作,但我需要的是格式化和对齐单元格值。

是否有一个属性可以添加到我的字段(HeightMeter)中,以便它可以根据需要对齐和格式化。要在手动列创建代码中执行此操作,您将使用以下内容:

DataGridViewColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
DataGridViewColumn.DefaultCellStyle.Format = "N2";

如何在使用 AutoGenerateColumns 解决方案时指定 DefaultCellStyle 属性 - 注意我仅限于使用 .net 2 :(

以下是我需要的和我得到的示例:

public partial class Form1 : Form
{
  private List<Person> people = new List<Person>();
  private DataGridView dataGridView1 = new DataGridView();
  private DataGridView dataGridView2 = new DataGridView();
  public Form1()
  {
    InitializeComponent();
    dataGridView1.Dock = DockStyle.Top;
    dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

    dataGridView2.Dock = DockStyle.Top;
    dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

    Controls.Add(dataGridView2);
    Controls.Add(dataGridView1);

    Load += new EventHandler(Form1_Load);
    Text = "";
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    PopulateLists();
    dataGridView1.AutoGenerateColumns = true;
    dataGridView1.DataSource = people;

    CreateAndPopulateGrid2();
  }

  public void CreateAndPopulateGrid2()
  {
    DataGridViewColumn columnName = new DataGridViewTextBoxColumn();
    columnName.HeaderText = "Name";

    DataGridViewColumn columnHeight = new DataGridViewTextBoxColumn();
    columnHeight.HeaderText = "Height [m]";
    columnHeight.ValueType = typeof(double);

    columnHeight.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
    columnHeight.DefaultCellStyle.Format = "N2";
    dataGridView2.Rows.Clear();
    dataGridView2.Columns.Clear();
    dataGridView2.Columns.Add(columnName);
    dataGridView2.Columns.Add(columnHeight);

    DataGridViewRow row;
    foreach (Person p in people)
    {
      row = new DataGridViewRow();
      row.CreateCells(dataGridView2);
      row.Cells[0].Value = p.Name;
      row.Cells[1].Value = p.HeightMeter;
      dataGridView2.Rows.Add(row);
    }
  }

  private void PopulateLists()
  {
    people.Clear();
    people.Add(new Person("Harry", 1.7523));
    people.Add(new Person("Sally", 1.658));
    people.Add(new Person("Roy", 2.158));
    people.Add(new Person("Pris", 1.2584));
  }
}

class Person
{
  [System.ComponentModel.DisplayName("Name")]
  public string Name { get; set; }
  [System.ComponentModel.DisplayName("Height [m]")]
  public double HeightMeter { get; set; }

  public Person(string name, double heightMeter)
  {
    Name = name;
    HeightMeter = heightMeter;
  }
}

最佳答案

使用自定义属性控制 DataGridView 列的外观

DataGridView中自动生成列时,内置支持一些属性,包括ReadOnlyDisplayName可浏览 属性。例如,如果您使用 Browsable(false) 标记属性,则该属性不会作为列添加到 DataGridView 中。

但是对于Format,没有这样的内置支持。您可以创建自定义 DisplayFormat 属性,并编写一些代码以在自动生成列后在 DataGridView 中使用它。

例如,假设您有一个这样的类(class):

using System;
using System.ComponentModel;
public class Product
{
    [DisplayName("Code")]
    [Description("Unique code of the product")]
    public int Id { get; set; }

    [DisplayName("Product Name")]
    [Description("Name of the product")]
    public string Name { get; set; }

    [DisplayName("Unit Price")]
    [Description("Unit price of the product")]
    [DisplayFormat("C2")]
    public double Price { get; set; }
}

因此,我们将得到一个像屏幕截图一样的 DataGridView,它可以看到我们使用 Description 属性的值作为列的工具提示文本,并且我们使用 DisplayFormat 以货币格式显示价格:

enter image description here

首先,我们应该为格式创建自定义属性,DisplayFormat:

using System;
using System.ComponentModel;
public class DisplayFormatAttribute : Attribute
{
    public DisplayFormatAttribute(string format)
    {
        Format = format;
    }
    public string Format { get; set; }
}

然后加载数据并自动生成列,例如:

var list = new List<Product>() {
    new Product(){ Id=1, Name="Product 1", Price= 321.1234},
    new Product(){ Id=2, Name="Product 2", Price= 987.5678},
};
this.dataGridView1.DataSource = list;

然后,为了利用属性,您可以编写不依赖于模型类型的代码:

var type = ListBindingHelper.GetListItemType(dataGridView1.DataSource);
var properties = TypeDescriptor.GetProperties(type);
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
    var p = properties[column.DataPropertyName];
    if (p != null)
    {
        var format = (DisplayFormatAttribute)p.Attributes[typeof(DisplayFormatAttribute)];
        column.ToolTipText = p.Description;
        column.DefaultCellStyle.Format = format == null ? null : format.Format;
    }
}

您可以简单地将上述代码封装在诸如 void SetupColumn(DataGridView dgv) 之类的方法中,或者如果您有派生的 DataGridView,则可以创建一个 DataBind( object data) 方法,并在该方法中将 data 分配给 DataSource,然后使用上面的代码作为方法主体的其余部分。

注意

我还在您的问题下的评论中读到,您已经告诉“...每个字段都有点多。”如果出于任何原因您不喜欢属性方法,您可以可以简单地坚持这样的 for 循环:

foreach (DataGridViewColumn c in dataGridView1.Columns)
{
    if (c.ValueType == typeof(double))
    {
        c.DefaultCellStyle.Format = "C2";
        c.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
    }
}

Windows 窗体中的 DataAnnotations 属性

要了解如何在 Windows 窗体中将数据注释属性用于 DataGridView 和验证,请查看以下帖子:

关于c# - 设置具有对象 DataSource 的 DataGridView 中自动生成的列的格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50852375/

相关文章:

c# - 通缉 : List of data following certain rules concerning dates

c# - 保存表单状态然后以相同状态打开它

c# - 在 Winforms web 浏览器控件中使用 ActiveXObject

c# - 将 DataGridView 单元格多选限制为仅列或行

c# - Windows 窗体 : change dataGridView's first cell origin?

c# - MS 图表控制量表 - 折线图显示 12 个月

c# - 从巨大的文本文件中读取特定行(c# 4.0)

c# - 如何使用颜色对话框仅将颜色应用于 C# 中的选定文本

.net - 如何安全访问 DataGridView 列名?

c# - CultureInfo.NumberFormat 隐藏逗号