4

I have a DB and I created classes to access/manage it using SQLMetal. Now, I use LINQ to SQL, and I want to display the result of queries in a data grid view. when I do that, the columns are named after my columns in the DB table, and all the properties are displayed. I know I could change this by using DisplayName and Browseable attributes, but because the classes are auto-generated I can't just add this attributes where there are needed. I came up with three workarounds:

  1. creating an Adopter to adopt my classes. I'm still not sure how exactly you make an adopter for this case.
  2. creating another program that will run after the generating of the code that will add the attributes. this seems like an hack, and I prefer to separate between the functionality and the GUI, so this method is on hold.
  3. using the MetaDataType attribute. I couldn't get this to work, and it's requires, as far as I know, that the classes and the metadata class will be in the same DLL.

How do I do the customization? is there another way? what way should I take and how?

EDIT: forgotten to mention: I'm using winforms, but if it will simplify things, I will move to WPF.

nathanchere
  • 8,008
  • 15
  • 65
  • 86
elyashiv
  • 3,623
  • 2
  • 29
  • 52

3 Answers3

5

You can set a Types Metadata Type at run time by registering it with the TypeDescriptor manually.

That goes something like this.

var type = typeof(Foo);
var metadataType = typeof(FooMetadata);
TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(type, metadataType), type);

To show it all in context this will show a single column in the data grid with the header "Custom Bar".

public class Foo
{
    public string Bar { get; set; }
    public string DontShowMe { get; set; }
}

public class FooMetadata
{
    [DisplayName("Custom Bar")]
    public string Bar { get; set; }

    [Browsable(false)]
    public string DontShowMe { get; set; }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        var type = typeof(Foo);
        var metadataType = typeof(FooMetadata);
        TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(type, metadataType), type);

        this.dataGridView1.DataSource = new List<Foo> { new Foo { Bar = "Foobar" } };
    }
}

The is also a TypeDescriptor.RemoveProviderTransparent if you want to switch the Metadata Type on the go but keep in mind that setting/unsetting it applies to the whole application domain and so threading needs to be taken into account.

David Ewen
  • 3,632
  • 1
  • 19
  • 30
  • Are any of the `Foo` and `FooMetadata` types auto-generated?! – C.B. Oct 08 '13 at 21:22
  • When I use this pattern Foo is an auto generated type by linq2sql and FooMetadata is created manually with data annotations for display and validation. I use units test to flag any differences in the properties of both types so they don't go unnoticed. – David Ewen Oct 08 '13 at 22:59
  • I wonder , why TypeDescriptor.RemoveProviderTransparent is not working for me ... Any Suggestion ? – Bimal Das Nov 11 '17 at 09:41
1

By using the WPF DataGrid you can easily customize the auto generated columns by using the AutoGeneratingColumn event.

Ponraja
  • 570
  • 2
  • 6
  • 17
-1

Why can't you use the data grid view's Columns collection to change DisplayNames and Visibles at runtime?

C.B.
  • 666
  • 3
  • 18
  • I can. It just requires a lot of unmanageable code, and complex queries will result a pain in the heck. – elyashiv Oct 03 '13 at 12:34
  • But then you might add a module to your software that specifically manages these things... – C.B. Oct 04 '13 at 15:00