简体   繁体   English

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

[英]Set Format of auto-generated columns in DataGridView having object DataSource

I would like to auto create all the columns for my DataGridView based on my custom class.我想根据我的自定义类为我的DataGridView自动创建所有列。 Every thing works like it should, but what I need is to format and align the cell values.每件事都像它应该的那样工作,但我需要的是格式化和对齐单元格值。

So is there an attribute that I can add to my field (HeightMeter) so that it can align and format as required.那么是否有一个属性可以添加到我的字段(HeightMeter)中,以便它可以根据需要进行对齐和格式化。 To do this in a manual column create code, You will use the following:要在手动列创建代码中执行此操作,您将使用以下内容:

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

How to I specify the DefaultCellStyle properties when using the AutoGenerateColumns solution - Note I am limited to using .net 2 :(使用 AutoGenerateColumns 解决方案时如何指定 DefaultCellStyle 属性 - 注意我仅限于使用 .net 2 :(

Here is a sample of what I need and what I get:这是我需要什么和我得到什么的示例:

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;
  }
}

Using custom attributes to control appearance of DataGridView columns使用自定义属性控制 DataGridView 列的外观

When auto-generating columns in DataGridView , there is built-in support for a few attributes including ReadOnly , DisplayName and Browsable attribute.DataGridView自动生成列时,内置了对一些属性的支持,包括ReadOnlyDisplayNameBrowsable属性。 For example, if you mark a property using Browsable(false) it will not be added as a column to DataGridView .例如,如果您使用Browsable(false)标记一个属性,它将不会作为列添加到DataGridView

But for Format , there is no such built-in support.但是对于Format ,没有这样的内置支持。 You can create a custom DisplayFormat attribute and write some code to use it in DataGridView after auto generating columns.您可以创建自定义DisplayFormat属性并编写一些代码以在自动生成列后在DataGridView使用它。

For example, let's say you have a class like this:例如,假设您有一个这样的类:

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; }
}

And as a result, we are going to have a DataGridView like the screenshot, which can see we used the value of Description attribute as tooltip text for columns and also we used DisplayFormat to show the price in currency format:结果,我们将有一个像截图一样的DataGridView ,它可以看到我们使用Description属性的值作为列的工具提示文本,并且我们还使用DisplayFormat以货币格式显示价格:

在此处输入图片说明

First we should create the custom attribute for format, DisplayFormat :首先,我们应该为格式创建自定义属性DisplayFormat

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

Then load data and auto generate columns, for example:然后加载数据并自动生成列,例如:

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;

Then to take advantage of attributes, you can write such code which is not dependent to the model type:然后为了利用属性,您可以编写不依赖于模型类型的代码:

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;
    }
}

You can simply encapsulate above code in a method like void SetupColumn(DataGridView dgv) or if you have a derived DataGridView , you can create a DataBind(object data) method and in the method, assign data to DataSource and then use above code as rest of body of the method.您可以简单地将上面的代码封装在像void SetupColumn(DataGridView dgv)这样的方法中,或者如果您有派生的DataGridView ,您可以创建一个DataBind(object data)方法,并在该方法中,将data分配给DataSource ,然后使用上面的代码作为休息方法的主体。

Note笔记

I also read in the comments under your question that you have told ' ...for each field is a bit much.我还在您的问题下的评论中读到了您所说的“ ......因为每个领域都有点多。 ' If for any reason you don't like the attribute approach, you can simply stick to a for loop like this: ' 如果出于任何原因您不喜欢属性方法,您可以简单地坚持这样的 for 循环:

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

DataAnnotations attributes for in Windows Forms Windows 窗体中的 DataAnnotations 属性

To see how can you use data annotations attribute in Windows Forms for DataGridView and also for Validation, take a look at these posts:要了解如何在 Windows 窗体中为 DataGridView 和验证使用数据注释属性,请查看以下帖子:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM