Luka Ćetković Luka Ćetković - 1 month ago 5
C# Question

How to display a Browsable(false) Property in DataGridView

I want to display the

property of the
in a

dataGridView1.DataSource = ServiceController.GetServices();

It does not add the
property. As far as I was able to find out this is due to the
attribute of the property.

But when I add columns manually like this:

dataGridView1.ColumnCount = 2;
dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns[0].Name = "Machine Name";
dataGridView1.Columns[0].DataPropertyName = "MachineName";
dataGridView1.Columns[1].Name = "Display Name";
dataGridView1.Columns[1].DataPropertyName = "DisplayName";

BindingSource bs = new BindingSource();
bs.DataSource = ServiceController.GetServices();
dataGridView1.DataSource = bs;

I expect the
column to be filled when in fact while the column gets created the value displayed in the column is empty.

Is there a workaround so I can display this property?

Not a duplicate:

I'm not trying to override the datagrid view control so the AutoGenerateColumns Property of datagrid view will be visible in designer. I'm trying to Display a ServiceController Property with
attribute in the DataGridView

My final solution for anyone that is interested:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
if (e.ColumnIndex < 0 || e.RowIndex < 0)
if ( this.dataGridView1.Columns[e.ColumnIndex].DataPropertyName == "MachineName")
var model = this.dataGridView1.Rows[e.RowIndex].DataBoundItem as ServiceController;
if (model != null)
e.Value = model.MachineName;


Here the column is not auto-generated. It's generated but the value of cell is null because the property is not browsable.

There are multiple solutions to solve the problem, including:

  • Use CellFormatting event and provide value for cell.
  • Shape the result in a model or anonymous object with the same property names.
  • Using MetaDataType Attribute and provide new metadata for class.

Using CellFormatting

You can use CellFormatting and find the DataBound item behind the row and use the value of property directly from the model:

void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    if (e.ColumnIndex < 0 || e.RowIndex < 0)
    var model = this.dataGridView1.Rows[e.RowIndex].DataBoundItem as Model;
    if (model != null)
        e.Value = model.SomeField;

Shape the result

You can shape the result of your query to a model or anonymous object having the same property names as your original model to preserve column settings:

dataGridView1.DataSource = list.Select(x => new { Field1= x.Field1, Field2 = x.Field2 })

Using MetaDataType Attribute and provide new metadata for class

As another option you can use me metadata class for your model containing metedata attributes like Browsable or DisplayName and then register thar metadata class for your original model using MetadataType attribute and then register an AssociatedMetadataTypeTypeDescriptionProvider as TypeDescriptor for your class.

This method is useful to separate metadata from model.

It's really simple and really useful. All ASP.NET MVC developers are familiar with this approach but Windows Forms Developers usually don't know about such approach. To see a simple example and more description about it take a look at this post: