Проблема с установкой столбца «невидимым» в сетке * Событие 1001 * заключается в том, что, хотя область выполнения находится в событии CellValueChanged
, сетка НЕ даст вам НИКАКОЙ информации о «где»пользователь щелкнул / переместил «в» после того, как изменилось значение ячеек.
Это ВСЕГДА оставит скрытие столбца (в этом случае) подверженным ошибкам, поскольку мы не знаем, «где» пользователь щелкнул /переехал. Из-за этого может показаться очевидным, что если мы хотим избежать ошибки, нам придется «скрыть» столбец в каком-то другом событии.
Другая проблема, с которой вы можете столкнуться, заключается в том, что некоторые события неэто нравится, когда вы пытаетесь «изменить» ячейку «выделенной» сетки, что мы и делаем, когда пользователь нажимает на столбец, который мы хотим сделать невидимым. Нам нужно «изменить» выбранную ячейку на другую, чтобы избежать ошибки.
Учитывая это, ниже приведен хакерский подход, который может помочь. Имейте в виду, что не было большого количества тестирования кода и возникла одна проблема / ошибка, когда пользователь щелкнул заголовок столбца (чтобы отсортировать) для первого столбца. Это вызвало сбой, и я закончил тем, что отключил «сортировку» для этого столбца.
Небольшой пример ниже использует эту логику ... A DataGridView
с четырьмя (4) текстовыми столбцами установлено в формеи заполнены некоторыми данными. ConditionColumn
(столбец 0) в сетке - это столбец «условия», и он имеет строковые значения от 0 до 19. Именно в этом столбце будет «когда» «скрываться» HideColumn
(столбец 2).
ЕСЛИ значение, превышающее двадцать (20), вводится в любую ячейку в ConditionColumn,
ТОГДАHideColumn
будет установлено как невидимое. Существует небольшая функция AllCellsLessThan20
, которая перебирает все строки в сетке и проверяет ячейки ConditionColumn
на наличие значений, превышающих 20. Если хотя бы одно значение ячейки больше 20, то функция вернет false,Это используется для включения или выключения скрытого столбца, так что если ВСЕ ячейки в ConditionColumn
меньше 20, то столбец будет показан. В противном случае, если одна или несколько ячеек больше 20, столбец будет скрыт.
Чтобы избежать описанной ошибки, код установит столбец как невидимый в событии grid SelectionChanged
. Это событие сработает «после» события CellValueChanged
, если пользователь выберет другую ячейку любым способом… щелчком, вкладкой или клавишами со стрелками. Мы проверим несколько вещей, чтобы определить, нужно ли нам скрыть или показать столбец.
Очевидно, поскольку это событие называется ПОСЛЕ запускаемого события CellValueChange
, сетка не даст нам ЛЮБОЙ информации о «где»Ранее выбранная ячейка была. Отсюда и глобальные переменные. Установка этих глобальных значений в событии CellValueChanged
сделает их доступными в событии SelectionChanged
.
Возможно, некоторые переменные, такие как: ColumnShown
: bool
, указывают, скрыт или отображается столбец в данный момент. ValueGreaterThan20
: bool
для указания, является ли какое-либо значение в ConditionColumn
больше 20, и PreviousRow
: int
для указания индекса строки последней «измененной» ячейки.
bool ColumnShown = true;
bool ValueGreaterThan20 = false;
int PreviousRow = 0;
Установите столбцы сетки с некоторыми полезными именами, чтобы избежать проблем с индексацией, затем заполните сетку некоторыми тестовыми данными.
public Form1() {
InitializeComponent();
dataGridView1.Columns[0].Name = "ConditionColumn";
dataGridView1.Columns[0].HeaderText = "Condition";
dataGridView1.Columns[2].Name = "HideColumn";
dataGridView1.Columns[2].HeaderText = "Hide Column";
}
private void Form1_Load(object sender, EventArgs e) {
FillGrid();
}
private void FillGrid() {
for (int i = 0; i < 20; i++) {
dataGridView1.Rows.Add(i, "C1R" + i, "C2R" + i, "C3R" + i);
}
}
Далее - функция, которая проверяет, больше ли любое значение в ConditionColumn
, чем20.
private bool AllCellsLessThan20() {
foreach (DataGridViewRow row in dataGridView1.Rows) {
if (row.Cells[0].Value != null) {
string sValue = row.Cells["ConditionColumn"].Value.ToString();
if (int.TryParse(sValue, out int value)) {
if (value > 20) {
return false;
}
}
}
}
return true;
}
Далее идет событие grid CellValueChanged
. Здесь нам нужно проверить только две вещи: 1) изменилось ли значение в столбце 0 ConditionColumn
, и поскольку значение в этом столбце изменилось, нам нужно проверить ВСЕ значения. Если какое-либо значение превышает 20, установите для переменной ValueGreaterThan20
значение true
, в противном случае false
. Кроме того, мы сохраним индекс строки (PreviousRow
) измененной ячейки, поскольку мы захотим использовать его в событии SelectionChanged
.
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (e.ColumnIndex == 0) {
if (AllCellsLessThan20())
ValueGreaterThan20 = false;
else
ValueGreaterThan20 = true;
}
PreviousRow = e.RowIndex;
}
Событие SelectionChanged
указано ниже. Я знаю, что это может быть более компактным. Сначала выполняется проверка, чтобы увидеть, показан ли столбец или скрыт.
Если столбец уже «скрыт», то нам просто нужно выполнить chУбедитесь, что хотя бы одно значение в ConditionColumn
больше 20, и просто оставьте его скрытым. Если все значения меньше 20, то мы хотим отменить скрытие столбца.
Если столбец НЕ «скрыт», то мы проверяем, являются ли какие-либо значения больше 20. Если никакие значения не большечем 20, то просто оставьте столбец видимым.
Если столбец НЕ «скрыт», а одно или несколько значений больше 20, то нам нужно проверить, является ли текущий выбор столбцом, который мыхочу спрятатьсяЕсли текущий выбор НЕ является столбцом, который мы хотим скрыть, просто спрячьте его, так как мы знаем, что это не выдаст ошибку.
Наконец, если столбец НЕ «скрыт» И есть значение больше20 И текущий выбор - это столбец, который мы хотим скрыть. В этом случае код установит / изменит CurrentCell
на первую ячейку в PreviousRow
. Затем установите для столбца значение «Невидимый» и задайте глобальную переменную ColumnShown.
. В моем тесте, если пользователь изменяет ячейку в столбце 0 на значение, превышающее 20, тогда «Клики» по ячейке в столбце 2 HideColumn
, тогда ошибка не появляется, и выбор изменяется на первую ячейку в предыдущем ряду.
private void dataGridView1_SelectionChanged(object sender, EventArgs e) {
if (ColumnShown) {
if (ValueGreaterThan20) {
int curColIndex = dataGridView1.CurrentCell.ColumnIndex;
if (dataGridView1.Columns[curColIndex].Name == "HideColumn") {
dataGridView1.CurrentCell = dataGridView1.Rows[PreviousRow].Cells["ConditionColumn"];
dataGridView1.CurrentCell.Selected = true;
}
dataGridView1.Columns["HideColumn"].Visible = false;
ColumnShown = false;
}
}
else {
if (!ValueGreaterThan20) {
dataGridView1.Columns["HideColumn"].Visible = true;
ColumnShown = true;
}
}
}
Как я уже сказал, это хакерское решение, но оно работает с некоторыми оговорками. Надеюсь, это поможет!