Как предотвратить превращение пустой строки в DBNull.Value, когда DGV привязан к DataTable - PullRequest
0 голосов
/ 21 марта 2019

Трудно опубликовать код, но легко описать, как воспроизвести:

Создание нового проекта Winforms (я использовал VS 2017 и .NET 4.7)

  1. Добавить набор данных в проект.
  2. В DataSet добавьте DataTable (без адаптера).
  3. В DataTable добавьте один столбец. По умолчанию это varchar, но измените его, чтобы НЕ разрешать нули.
  4. Добавить форму в проект.
  5. Добавить DataGridView в форму.
  6. Установите для источника данных для DGV значение DataTable в наборе данных.
  7. Запустите программу.
  8. Нажмите в одном столбце одной строки.
  9. Введите контент.
  10. Выберите все содержимое и нажмите клавишу Backspace.
  11. Нажмите на появившуюся пустую вторую строку.

Что происходит: возникает исключение System.Data.NoNullAllowedException, указывающее, что столбец данных не допускает DBNull.Value.

Что должно произойти: столбец в строке, привязанной к первой строке dgv, должен быть пустым, а не нулевым.

Что я пробовал:

  • Использование обработчика CellEndEdit для обнаружения неверного значения и преобразования его в string.Empty. Это действительно исправляет НЕКОТОРЫЕ случаи (когда имеется более одного столбца)
  • Использование обработчика CellValidating - бесполезно
  • Использование обработчика CellFormatting - бесполезно
  • Использование обработчика CellParsing - бесполезно
  • Использование обработчика AddingNew в BindingSource для предоставления новых строк, имеющих ненулевые значения - бесполезно

Есть еще идеи?

Ответы [ 2 ]

2 голосов
/ 21 марта 2019

DataGridView можно настроить для учета желаемого варианта использования для отправки Empty.String при получении нулевого ввода.

От: Свойство DataGridViewCellStyle.DataSourceNullValue

Получает или задает значение, сохраненное в источнике данных, когда пользователь вводит нулевое значение в ячейку.

От: Свойство DataGridViewColumn.DefaultCellStyle

Получает или задает стиль ячейки столбца по умолчанию.

Указанные выше свойства используются для настройки DataGridView. Тем не менее, DataTable нуждается в небольшом изменении.

От: Свойство DataColumn.DefaultValue

Получает или задает значение по умолчанию для столбца при создании новых строк.

Можно подумать, что свойство DefaultNewRowValue DataGridVierwColumn CellTemplate *1033* предоставит это, но не в случае с привязанным столбцом. Если используются дополнительные столбцы, и это свойство не изменяется по умолчанию, исходная проблема будет всплывающим.

Следующий пример предназначен для решения вашей проблемы, как описано в ваших рекомендациях по воспроизведению, и предполагает, что для DataGridview.DataSource установлено значение DataTable или DataView. Он использует событие DataGridView.BindingContextChanged для обработки автоматически сгенерированных столбцов DataGridView после установки свойства DataSource.

public partial class Form1 : Form
{
    private DataTable dt;
    public Form1()
    {
        InitializeComponent();
        dataGridView1.BindingContextChanged += new System.EventHandler(this.dataGridView1_BindingContextChanged);
        dt = new DataTable();
        DataColumn dc = dt.Columns.Add("C0");
        dc.AllowDBNull = false;
        dataGridView1.DataSource = dt.DefaultView;
    }

    private void dataGridView1_BindingContextChanged(object sender, EventArgs e)
    {
        if (dataGridView1.DataSource != null)
        {
            DataTable boundTable = dataGridView1.DataSource as DataTable;
            if (boundTable == null)
            {
                DataView dv = dataGridView1.DataSource as DataView;
                if (dv != null)
                {
                    boundTable = dv.Table;
                }
            }
            if (boundTable != null)
            {
                foreach (DataGridViewColumn c in dataGridView1.Columns)
                {
                    if (c.IsDataBound)
                    {
                        DataColumn dc = boundTable.Columns[c.DataPropertyName];
                        if (!dc.AllowDBNull && dc.DataType == typeof(string))
                        {
                            c.DefaultCellStyle.DataSourceNullValue = string.Empty;
                            dc.DefaultValue = string.Empty;  // this value is pulled for new rows
                        }
                    }
                }
            }
        }
    }
}
1 голос
/ 21 марта 2019

Это выглядит как приемлемое решение - настройте по мере необходимости, чтобы избавиться от жестко привязанных индексов столбцов и т. Д.

private void dataGridView1_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
  var dgv = sender as DataGridView;
  if (null != dgv)
  {
    var row = dgv.Rows[e.RowIndex];
    var drv = row.DataBoundItem as DataRowView;
    if (null != drv)
    {
      var dr = drv.Row as DataSet1.DataTable1Row;
      if (dr.IsNull(0))
      {
        dr.Path = string.Empty;
      }
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...