Search code examples
c#datagridviewiformatprovider

DataGridView custom formatting: parse edited value


Suppose I have a DataGridView that is bound to a BindingSource. The BindingSource has a DataSource of class MyClass

public class MyClass
{
    public double Percentage {get; set;}
    ...
}

The DataGridView shows the percentage as a double. So a value of 19% is displayed as 0.19, which is not what I want.

Luckily I can change the cell style of the column:

dataGridViewCellStyle.Format = "p";

This makes that the value is displayed as a percentage according to the current culture. In my culture 0.19 is displayed as 19%.

So far so good. But what happens if an operator changes this value to 18% and ends editing the cell.

  • Event CellValidating is raised. In this event I can check that the entered text is a perfect percentage.

However, immediately after that I get an exception that the string "18%" cannot be formatted to a double.

I guess I have to tell the datagridviewCellStyle which formatprivider to use:

datagridVieCellStyle.FormatProvider = new MyFormatProvider();

class MyFormatProvider : IFormatProvider
{
    public object GetFormat(Type formatType)
    {
        // what to return?
    }
}

Question Suppose I have the following class:

public static class PercentStringParser
{
     public static double Parse(string txt);
}

How should my format provider make that this function is called?


Solution

  • Do not use the format provider, but use event DataGridView.CellParsing.

    private void OnCellParsing(object sender, DataGridViewCellParsingEventArgs e)
    {
        if (e.ColumnIndex == this.percentageDataGridViewTextBoxColumn.Index
            && e.DesiredType == typeof(double)
            && ContainsPercentSign(e.Value.ToString()))
            {   // parsing a percentage to a double
                var formatProvider = this.dataGridView1.Rows[e.RowIndex]
                                         .Cells[e.ColumnIndex]
                                         .InheritedStyle
                                         .FormatProvider;
    
                try
                {
                    e.Value = ParsePercentageToDouble(e.Value.ToString(), formatProvider);
                    e.ParsingApplied = true;
                }
                catch (FormatException)
                {
                    e.ParsingApplied = false;
                }
            }
            else
            {   // parsing any other column, let the system parse it
                e.ParsingApplied = false;
            }           
        }
    }
    

    MSDN example about this event