У меня есть DataGridView с столбцами «Тип» и «Значение». Пользователь выбирает тип данных и затем вводит значение, совместимое с этим типом, некоторые типы (например, «Текст») принимают любую строку. Другие типы (например, «Да/Нет») ограничены списком возможных значений. Для каждой строки я устанавливаю ячейку в столбце «Значение» как текстовое поле для типов произвольной формы, либо для списка типов списков. DataGridView привязан к DataTable.Пустая ячейка Datagridview со связанным datasourse
Проблема возникает, если пользователь вводит значение для одного типа, но затем переключает строку на другой тип, для которого текущее значение недопустимо. Независимо от того, что я пытаюсь, я не могу очистить ячейку Value. Затем, когда я назначаю combobox для ячейки, я получаю DataError, потому что текущее значение ячейки несовместимо. Как очистить значение до изменения ячейки из текстового поля в поле со списком?
public enum DataType
{
Text,
YesNo
}
public class IndexedItem
{
public string Name { get; set; }
public int ID {get; set; }
public string strID
{
get { return ID.ToString(); }
}
//constructors & other methods;
}
public static DataTable ParameterTable;
public List<IndexedItem> YesNoList;
В виде конструктора (dgvInputs является DataGridView):
ParameterTable = new DataTable("ParameterTable");
ParameterTable.Columns.Add("Type", typeof(DataType));
ParameterTable.Columns.Add("Value", typeof(string));
YesNoList = new List<IndexedItem>();
YesNoList.Add(new IndexedItem("Yes", 1));
YesNoList.Add(new IndexedItem("No", 0));
var D = (DataGridViewComboBoxColumn)dgvInputs.Columns[0];
D.ValueMember = "Value";
D.DisplayMember = "Display";
D.DataSource = new DataType[] {
DataType.Text,
DataType.YesNo
}.Select(x => new { Display = x.ToString(), Value = (int)x }).ToList();
BindingSource ParamSource = new BindingSource();
ParamSource.DataSource = ParameterTable;
dgvInputs.AutoGenerateColumns = false;
dgvInputs.DataSource = ParamSource;
dgvInputs.Columns[0].DataPropertyName = "Type";
dgvInputs.Columns[1].DataPropertyName = "Value";
и события:
private void dgvInputs_CurrentCellDirtyStateChanged(object sender, EventArgs e) {
if (dgvInputs.IsCurrentCellDirty) {
dgvInputs.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
private void dgvInputs_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (e.RowIndex >= 0 && e.ColumnIndex == 0) {
var cb = (DataGridViewComboBoxCell)dgvInputs[0, e.RowIndex];
if (cb.Value != null && cb.Value != DBNull.Value) {
DataType Type = (DataType)cb.Value;
dgvInputs[1, e.RowIndex].Value = string.Empty;
dgvInputs.CommitEdit(DataGridViewDataErrorContexts.Commit);
switch (Type) {
case DataType.YesNo:
dgvInputs[1, e.RowIndex].Dispose();
var newBox = new DataGridViewComboBoxCell();
newBox.DisplayMember = "Name";
newBox.ValueMember = "strID";
newBox.DataSource = YesNoList;
dgvInputs[1, e.RowIndex] = newBox;
break;
default:
dgvInputs[1, e.RowIndex] = new DataGridViewTextBoxCell();
break;
}
}
}
}
Если у вас есть он установлен в "текст" и ввести что-то произвольное, то переключитесь на «YesNo», он выдаст ошибку «System.ArgumentException: значение DataGridViewComboBoxCell недопустимо». Это будет появляться в любое время, когда курсор находится над ячейкой. Изменение его в текстовой строке приводит к тому, что исходное значение снова появляется.
Я предполагаю, что проблема в том, что значение сохраняется в ParameterTable, но я не могу заставить его распространять мою очистку исходного значения ParameterTable. Я пробовал null
и DBNull.Value
вместо string.Empty
, но ни один не имел никакого значения. Я добавил строку «CommitEdit» в надежде заставить ее внести изменения, но это тоже не имело никакого значения.
Edit: Как оказалось, проблема была это код, который я имел в случае изменения клеток:
string Default = dgvInputs[4, e.RowIndex].Value as string;
// code switching out text box and combo box above
try
{
dgvInputs[4, e.RowIndex].Value = Default;
} catch (Exception e2) {
MessageBox.Show(e2.GetType().ToString());
}
Идея была в том, чтобы сохранить значение, если это возможно, и я имел чтобы показать мне конкретное исключение, которое мне нужно было поймать, поскольку я не был уверен. Но, очевидно, это задание не вызывает немедленного исключения. Это происходит только потом, видимо, во время какого-то другого события, с которым я не справляюсь.
Оглядываясь назад, я должен был включить этот код в образец. Я понятия не имею, как я это забыл. Приношу свои извинения всем, кого я привел в погоню за дикими гусями, оставив критическую информацию. Я очень ценю вашу помощь.
DBType Type = (DataType) cb.Value; не компилируется. –
Я скопировал код, исправил некоторые ошибки компиляции, запустил, выделил оба типа и вводил или выбирал значения, не выходил ни одного сообщения об ошибке. –
@LeiYang - Я строго усекретил код для примера и попытался изменить «DBType» на «DataType», потому что в некоторой библиотеке акций есть «DbType» (который я обнаружил только после того, как выбрал свое имя) я хочу смутить его. Я должен сам попробовать усеченный пример. Хотя я старался не делать этого, я, возможно, удалил что-то важное. –