0

I want to display the MachineName property of the System.ServiceProcess.ServiceController in a DataGridView control:

dataGridView1.DataSource = ServiceController.GetServices();

It does not add the MachineName property. As far as I was able to find out this is due to the [Browsable(false)] 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 MachineName 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 [Browsable(false)] 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)
        return;
    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;
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 2
    Possible duplicate of [DataGridView AutoGenerateColumns is set to true somehow](http://stackoverflow.com/questions/1189576/datagridview-autogeneratecolumns-is-set-to-true-somehow) – Khalil Khalaf Sep 23 '16 at 17:59
  • And which post exactly solves the problem? Here the columns doesn't auto-generate, but it doesn't show data. – Reza Aghaei Sep 23 '16 at 18:12

1 Answers1

1

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)
        return;
    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 })
                               .ToList();

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:

Community
  • 1
  • 1
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • CellFormatting worked just like I needed it to. Needed to tweak it slightly but then it worked like a charm. Thank you. – Luka Ćetković Sep 23 '16 at 18:42
  • There is also some really useful options like [this](http://stackoverflow.com/a/34481967/3110834) which I was going to add as an option. In the linked post it's enough to decorate meta-data properties with `[Browsable(true)]`. You will find this post really useful: [Is it possible to add an attribute to a property in a partial class?](http://stackoverflow.com/a/34481967/3110834) – Reza Aghaei Sep 23 '16 at 18:46
  • Thanks. But the 3rd option is very much out of my reach. Tried it for an hour or so but coudn't make it work. Probably because this is the first time I've encountered attributes and these other concepts. Thank you anyway very interesting post I will probably get back to. – Luka Ćetković Sep 23 '16 at 20:04
  • Don't worry, after you learned more about attributes and also .net meta data engines you will be able to use such mechanisms. To make it work, it's enough to follow the example in the linked post. If you got back to the post, let me know if you had any problem about applying the answer or if you asked a new question inspiring the post, feel free to notify me and I'll post a clean working example in response. – Reza Aghaei Sep 23 '16 at 20:14