DataGridViewColumn.DataPropertyName Property

2020-03-18 07:16发布

I have a DataGridView control and I want to populate it with data.

I use DataSource property

// dgvDealAsset is DataGridView
        private void DealAssetListControl_Load(object sender, EventArgs e)
        {
            dgvDealAssets.AutoGenerateColumns = false;
            dgvDealAssets.DataSource = DealAssetList.Instance.Values.ToList();
}

Now problem number one. The class of my collection does not contain only simple types that I can map to columns using DataPropertyName. This is the class that is contained in collection.

class MyClass
{
  public String Name;
  MyOtherClass otherclass;
}

class MyOtherClass
{
 public String Name;
}

Now I am binding properties of MyClass to columns

col1.DataPropertyName = "Name"  // Ok 
col2.DataPropertyName = "otherclass" // Not OK - I will have empty cell

The problem is that I want to display otherclass.Name field. But if I try to write

col2.DataPropertyName = "otherclass.Name" 

I get empty cell.

I tried to manually set the column

private void DealAssetListControl_Load(object sender, EventArgs e)
{
    dgvDealAssets.AutoGenerateColumns = false;
    dgvDealAssets.DataSource = DealAssetList.Instance.Values.ToList();

// iterate through rows and set the column manually
        foreach (DataGridViewRow row in dgvDealAssets.Rows)
        {
            row.Cells["Column2"].Value = ((DealAsset)row.DataBoundItem).otherclass.Name;
        }

But this foreach cycle takes about minute to complete (2k elements). How to solve this problem?

5条回答
家丑人穷心不美
2楼-- · 2020-03-18 07:19

DataGridView doesn't support databinding to child properties. For more info, check this post

I like the solution that uses the CellFormatting event.

查看更多
别忘想泡老子
3楼-- · 2020-03-18 07:26

It sounds like the DataGridView's virtual mode would solve your problem. In virtual mode, the DataGridView will fire an event whenever it needs to display a cell. The event lets you populate the cell however you please. The advantage of virtual mode is the system only needs to pull the data that's actually being displayed, so there's no slow start-up time while you load everything.

    private void my_init_function() {
        datagridview.VirtualMode = true;
        datagridview.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(datagridview_CellValueNeeded);
    }

    private void datagridview_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        e.Value = get_my_data(e.RowIndex, e.ColumnIndex);
    }
查看更多
Evening l夕情丶
4楼-- · 2020-03-18 07:28

The way of databinding a specific column of a datagrid to a child property of the datagrid's datasource is using the DataGridView.Column.Tag property, along with the ToString() override method inside the child object. It goes as follows:

public class Car
{
    public int Id { get; set; }

    public int Name { get; set; }

    public string Colour { get; set; }

    public Wheel Wheel { get; set; }
}

public class Wheel 
{
    public string WheelName { get; set; }

    public override string ToString()
    {
        return WheelName;
    }
}

public class Main
{
   private void LoadGrid(List<Car> data)
   {
       this.dataGridView.Columns["Wheel"].Tag = "WheelName";
   }
}
查看更多
ゆ 、 Hurt°
5楼-- · 2020-03-18 07:31

In case you want to use many child elements like this:

class MyClass
{
   public int Id;
   public MyOtherClass OtherClass;
}

class MyOtherClass
{
   public string Name;
   public int Number;
}

How about

1st solution Set value for each cell in some event (mabye other one is better), manually, after setting datasource, for example:

private void dgv_CellFormatting( object sender, DataGridViewCellFormattingEventArgs e )
{
   MyClass data = dgv.Rows[ e.RowIndex ].DataBoundItem as MyClass;

   dgv.Rows[ e.RowIndex ].Cells[ "colName" ].Value = data.OtherClass.Name;
   dgv.Rows[ e.RowIndex ].Cells[ "colNumber" ].Value = data.OtherClass.Number;
}

2nd solution What about creating a DataTable from the data and then bind it?

I'd be thankful for any opinion ;-)

查看更多
仙女界的扛把子
6楼-- · 2020-03-18 07:33

Problem nr.1:

Try to do the following:

  1. extend MyOtherClass from Object (this step might not be needed)

  2. and override, or create, method ToString().

That should do it.

查看更多
登录 后发表回答