【问题标题】:DataGridView: Object of type 'System.DBNull' cannot be converted to type 'System.Decimal'DataGridView:“System.DBNull”类型的对象无法转换为“System.Decimal”类型
【发布时间】:2021-06-09 14:33:48
【问题描述】:

我有一个绑定到 c# BindingList 的 c# DataGridView。用户可修改的文本列绑定到十进制值。当绑定对象的十进制值包含 0 时,空单元格正确显示为空而不是显示 0(即 CellFormatting 处理程序显示“”而不是 0)。如果用户输入 0,则将其传递给绑定对象并显示一个空单元格,这样一切正常。

如果用户清除单元格,我希望行为相同;但是,我得到了一个例外:

System.ArgumentException: Object of type 'System.DBNull' cannot be converted to type 'System.Decimal'.
   at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.PushValue(Int32 boundColumnIndex, Int32 columnIndex, Int32 rowIndex, Object value)

在 CellValidating 事件中我这样做:

string priceString = e.FormattedValue.ToString();
if (String.IsNullOrWhiteSpace(priceString))
{
  boundObject.decimalValue = 0;
}

因此,从某种意义上说,绑定对象确实将其十进制值正确设置为 0,但我想避免该异常。

e.FormattedValue 是只读的,所以我不能修改它;我也尝试过使用

dataGridView[e.ColumnIndex, e.RowIndex].Value = 0m;

但这并不能解决问题。

我可以在 CellValidating 中做些什么来避免这个问题吗?还是我需要在其他地方修改值(CellEndEdit?CellValueChanged?其他地方?)

谢谢!

【问题讨论】:

  • 感谢您的浏览。我在问题中添加了一些细节。 DataGridView 绑定到 c# 对象的 BindingList,而不是 DataTable。由于 CellFormatting(可能与问题无关),显示一个空单元格而不是 0。

标签: c# winforms datagridview


【解决方案1】:

新值需要在OnCellParsing(...) 方法中处理。例如:

public class Form5 : Form {
    
    public Form5() {
        List<Person> list = new List<Person>();
        list.Add(new Person { Name = "A", Age = 1 });
        list.Add(new Person {Name = "B", Age = 2 });
        list.Add(new Person {Name = "Z", Age = 0 });

        DGV dgv = new DGV { Dock = DockStyle.Fill };
        var bindingList = new BindingList<Person>(list);
        dgv.DataSource = bindingList;
        dgv.BindingContext = new BindingContext();

        Controls.Add(dgv);
    }

    public class DGV : DataGridView {
        ErrorProvider errorProvider = new ErrorProvider { BlinkStyle = ErrorBlinkStyle.NeverBlink };
        public DGV() {
            AllowUserToAddRows = false;
        }

        protected override void OnCellFormatting(DataGridViewCellFormattingEventArgs e) {
            base.OnCellFormatting(e);
            if (e.Value is decimal && ((decimal) e.Value) == 0m)
                e.Value = "";
        }

        protected override void OnCellParsing(DataGridViewCellParsingEventArgs e) {
            base.OnCellParsing(e);
            String s = e.Value.ToString();
            if (String.IsNullOrWhiteSpace(s)) {
                e.Value = 0m;
                e.ParsingApplied = true; // important, otherwise the value reverts back to the original value
            }
            else {
                decimal val = 0m;
                if (decimal.TryParse(s, out val))
                    e.Value = val;
            }
        }

        protected override void OnDataError(bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e) {
            base.OnDataError(false, e);
            Control c = this.EditingControl;
            errorProvider.SetError(c, e.Exception.Message);
            errorProvider.SetIconAlignment(c, ErrorIconAlignment.MiddleLeft);
            errorProvider.SetIconPadding(c, -20);
        }

        protected override void OnCellEndEdit(DataGridViewCellEventArgs e) {
            base.OnCellEndEdit(e);
            errorProvider.Clear();
        }
    }

    public class Person {
        public String Name { get; set; }
        public decimal Age { get; set; }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 2021-04-26
    • 2017-06-19
    相关资源
    最近更新 更多