views:

119

answers:

2

Following on a bit from this question, if I have this class:

private class MyClass {
  [DisplayName("Foo/Bar")]
  public string FooBar { get; private set; }
  public decimal Baz { get; private set; }
}

And I want to display a List<MyClass> in a DataGridView (with autogenerated columns), what's the easiest way to make the Baz column display formatted as currency?

Is there an attribute I can use like I'm using DisplayName, or do I have to mess with the columns after they are created?

+2  A: 

I know its not perfect but you could add another property called CurrencyBaz that would basically return a formatted Baz, then bind that to the grid instead of the real Baz.

so something like this.

private class MyClass {
  [DisplayName("Foo/Bar")]
  public string FooBar { get; private set; }
  [Browsable(False)]
  public decimal Baz { get; private set; }
  [DisplayName("Baz")]
  public CurrencyBaz
  {
        get { return string.Format(Baz, "C2"); }
  }
}
Keivan
That will work for me (fixed it a bit though ;). I'll accept if noone comes up with something better.
Blorgbeard
Although it won't right-align the column, of course.. Good enough for what I'm doing though :)
Blorgbeard
I can think of anything to get the alignment fixed,
Keivan
+2  A: 

TypeConverterAttribute - something like:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Forms;
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form { Controls = {
            new DataGridView {
                Dock = DockStyle.Fill,
                DataSource = new List<MyClass> {
                    new MyClass { FooBar = "abc", Baz = 123.45M},
                    new MyClass { FooBar = "def", Baz = 678.90M}
                }
            }
        }});
    }
}
class MyClass
{
    [DisplayName("Foo/Bar")]
    public string FooBar { get; set; }
    [TypeConverter(typeof(CurrencyConverter))]
    public decimal Baz { get; set; }
}
class CurrencyConverter : DecimalConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context,
        CultureInfo culture, object value)
    {
        string s = value as string;
        if (s != null) return decimal.Parse(s, NumberStyles.Currency, culture);
        return base.ConvertFrom(context, culture, value);
    }
    public override object ConvertTo(ITypeDescriptorContext context,
        CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            return ((decimal)value).ToString("C2", culture);
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}
Marc Gravell
That's pretty cool, I'll have to remember that. But for now, the class I'm making is only a private inner class for display in a list anyway - so it's probably better to use less code and deal with an extra property a la Kay.one's answer.
Blorgbeard
Also, nice example code! I just pasted the whole thing into SnippetCompiler and it ran.
Blorgbeard
Of course, stick `CurrencyConverter` away in your standard library somewhere and it **is** one line ;-p
Marc Gravell