使用DataSourceNullValue的DataGridView:输入nothing或nullValue

时间:2017-08-17 07:57:31

标签: c# .net winforms data-binding datagridview

我有一个DataGridView,它可以数据绑定到DataSource。

DataGridView的一个列绑定到十进制类型的属性? (可以为空的十进制)。此列可编辑。

如果属性的值为null,则底层对象应使用从另一个对象检索的默认值。

如果此列没有显示任何内容,则操作员似乎感到困惑。因此,我想显示字符串“<default>”,表示使用了默认值。

当编辑这个值时,我想让操作员自由地留下一个空字段,或者输入类似“<default>”的内容,如果他想表明应该使用默认值。所以:

  • 运算符输入字符串“<default>”:property gets value(decimal?)null
  • 运算符输入空字符串:属性获取值(十进制?)null
  • 运算符输入任何其他值:验证它是否为小数,并使用此值。

我尝试过的(总是第一次被要求: - )

public MyForm() // constructor
{
    this.InitializeComponent();

    // initialize datagridview (part of this could have been done in designer)
    this.dataGridView1.AutoGenerateColumns = false;
    this.dataGridView1.DataSource = ...;
    var valueCellStyle = this.columnNonDefault.DefaultCellStyle;
    valueCellStyle.DataSourceNullValue = (decimal?)null;
    valueCellStyle.NullValue = "<default>";
}

验证事件处理程序如下:

private void OnCellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    if (e.CollumnIndex == this.columnNonDefaultValue.Index)
    {   // validating the non-default value
        // allow either empty string, or cellStyle.NullValue or decimal
        string proposedValue = (string)e.FormattedValue;

        // check if empty:
        if (String.IsNullOrEmpty(proposedValue)
        {   // accept empty:
            e.Cancel = false;
        }
        else
        {   // check if "<default>"
            var cellToValidate = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
            DataGridViewCellStyle style = cellToValidate.InheritedStyle;
            if (!style.IsNullValueDefault
            && String.Equals(proposedValue, style.NullValue.ToString()))
            {   // accept default value:
                e.Cancel = false;
            }
            else if (this.IsProperDecimal(proposedValue)
            {    // accept decimal value
                 e.Cancel = false;
            }
            else
            {    // all others: don't accept
                 this.ShowInvalidData(...)
                 e.Cancel = true;
            }
        }
    }
}

如果人们输入正确的十进制值或“<default>”,这样可以正常工作。如果输入一个空字符串,那么只要数据被推送到数据绑定项,我就会得到字符串格式异常。

我原本以为我应该处理CellValuePushed事件,VirtualMode = true。唉,因为网格视图是数据绑定的,所以不会调用此事件,即使推送了正确的值也不会

那么我可以用什么来接受“”和空字符串为(decimal?)null?

1 个答案:

答案 0 :(得分:1)

作为选项,您可以使用CellParsingCellFormatting事件来处理输入值与数据源值之间的转换,并以合适的格式显示数据源值。

  • CellParsing:将输入的文本转换为合适的数据源值。

    在此您要根据某些条件将输入的值转换为默认值(当输入的文本为空或""或等于默认值时)。

  • CellFormatting:将数据源值转换为适合在单元格中显示的文本。

    您希望将默认值转换为某些文字,例如<Default>

以下是一个例子:

public class Test
{
    public int X { get; set; }
    public decimal? Y { get; set; }
}

BindingList<Test> list;
decimal? defaultValue = 100; //Some default value
string defaultFormattedValue = "<Default>"; //Some default formatted value

private void Form1_Load(object sender, EventArgs e)
{
    list = new BindingList<Test>(new List<Test>());
    this.dataGridView1.DataSource = list;
}

private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
    var value = string.Format("{0}", e.Value);
    if (value == string.Empty || value == "\"\"")
        e.Value = defaultValue;
    e.ParsingApplied = true;
}

private void dataGridView1_CellFormatting(object sender, 
    DataGridViewCellFormattingEventArgs e)
{
    if (e.Value is int? && (int?)e.Value == defaultValue)
        e.Value = defaultFormattedValue;
}