У меня есть DataGridView
(называемый SummaryDataGrid
) в классе форм Windows (называемый SummaryForm
), который я пытаюсь программно обновить с помощью раскрывающегося списка ComboBox
(называемого YearComboBox). SummaryDataGrid
не редактируется пользователем и просто используется для отображения информации в виде электронной таблицы. Я хочу иметь возможность использовать YearComboBox
, чтобы пользователь мог выбрать год, а затем SummaryDataGrid
обновить его значения на основе выбора этого года. Вы можете увидеть скриншот SummaryForm
по ссылке ниже, показывающий SummaryDataGrid
, заселенный к 2020 году.
YearComboBox
не привязан к данным, как и SummaryDataGrid
. Чтобы заполнить SummaryDataGrid
программно, я создаю DataGridViewRows
в SummaryForm
, а затем заполняю данные, извлекая их из моей базы данных SQL, используя функции, определенные в моем MainForm
, которые, в свою очередь, используют функции, определенные в моем наборе данных, который связан с моим SQL Server
, который я размещаю. Некоторые примеры кода можно найти ниже.
public partial class SummaryForm : Form
{
private DataGridViewRow JanuaryRow = new DataGridViewRow();
private DataGridViewRow FebruaryRow = new DataGridViewRow();
private DataGridViewRow MarchRow = new DataGridViewRow();
private DataGridViewRow AprilRow = new DataGridViewRow();
private DataGridViewRow MayRow = new DataGridViewRow();
private DataGridViewRow JuneRow = new DataGridViewRow();
private DataGridViewRow JulyRow = new DataGridViewRow();
private DataGridViewRow AugustRow = new DataGridViewRow();
private DataGridViewRow SeptemberRow = new DataGridViewRow();
private DataGridViewRow OctoberRow = new DataGridViewRow();
private DataGridViewRow NovemberRow = new DataGridViewRow();
private DataGridViewRow DecemberRow = new DataGridViewRow();
private DataGridViewRow TotalRow = new DataGridViewRow();
private DataGridViewRow AverageRow = new DataGridViewRow();
private int year = DateTime.Today.Year;
...
// form load event handler
private void SummaryForm_FormLoad(Object sender, EventArgs e)
{
YearComboBox.Text = year.ToString();
JanuaryRow.CreateCells(SummaryDataGrid);
FebruaryRow.CreateCells(SummaryDataGrid);
MarchRow.CreateCells(SummaryDataGrid);
AprilRow.CreateCells(SummaryDataGrid);
MayRow.CreateCells(SummaryDataGrid);
JuneRow.CreateCells(SummaryDataGrid);
JulyRow.CreateCells(SummaryDataGrid);
AugustRow.CreateCells(SummaryDataGrid);
SeptemberRow.CreateCells(SummaryDataGrid);
OctoberRow.CreateCells(SummaryDataGrid);
NovemberRow.CreateCells(SummaryDataGrid);
DecemberRow.CreateCells(SummaryDataGrid);
TotalRow.CreateCells(SummaryDataGrid);
AverageRow.CreateCells(SummaryDataGrid);
// populate january row
JanuaryRow.Cells[0].Value = "January";
JanuaryRow.Cells[1].Value = MainFormInstance.BillsOfSaleCountMonth(1, year);
JanuaryRow.Cells[2].Value = MainFormInstance.BillsOfSaleCashMonth(1, year);
JanuaryRow.Cells[3].Value = MainFormInstance.BillsOfSaleCreditMonth(1, year);
JanuaryRow.Cells[4].Value = Convert.ToDecimal(JanuaryRow.Cells[2].Value) + Convert.ToDecimal(JanuaryRow.Cells[3].Value);
JanuaryRow.Cells[5].Value = MainFormInstance.CashMonth(1, year);
JanuaryRow.Cells[6].Value = MainFormInstance.CardMonth(1, year);
JanuaryRow.Cells[7].Value = MainFormInstance.MonthCP(1, year);
JanuaryRow.Cells[8].Value = MainFormInstance.ExpensesMonthCP(1, year) + MainFormInstance.BillsOfSaleCashMonth(1, year);
JanuaryRow.Cells[9].Value = Convert.ToDecimal(JanuaryRow.Cells[7].Value) - Convert.ToDecimal(JanuaryRow.Cells[8].Value);
JanuaryRow.Cells[10].Value = MainFormInstance.MonthCF(1, year);
JanuaryRow.Cells[11].Value = MainFormInstance.ExpensesMonthCF(1, year);
JanuaryRow.Cells[12].Value = Convert.ToDecimal(JanuaryRow.Cells[10].Value) - Convert.ToDecimal(JanuaryRow.Cells[11].Value);
JanuaryRow.Cells[13].Value = MainFormInstance.ExpensesMonthGeneral(1, year);
JanuaryRow.Cells[14].Value = Convert.ToDecimal(JanuaryRow.Cells[5].Value) + Convert.ToDecimal(JanuaryRow.Cells[6].Value);
JanuaryRow.Cells[15].Value = Convert.ToDecimal(JanuaryRow.Cells[8].Value) + Convert.ToDecimal(JanuaryRow.Cells[11].Value) + Convert.ToDecimal(JanuaryRow.Cells[13].Value);
JanuaryRow.Cells[16].Value = Convert.ToDecimal(JanuaryRow.Cells[14].Value) - Convert.ToDecimal(JanuaryRow.Cells[15].Value);
SummaryDataGrid.Rows.Add(JanuaryRow);
...
}
// year combo box selection event handler
private void SummaryForm_YearChanged(Object sender, EventArgs e)
{
year = int.Parse(YearComboBox.Text);
PopulateSummaryDataGrid();
}
// populate the summary data grid
private void PopulateSummaryDataGrid()
{
// stubbed
}
Я определил обработчик событий SelectedValueChanged для YearComboBox
и сначала попытался перенести заполнение каждой строки в отдельную функцию из обработчика событий FormLoad
. Идея заключалась в том, чтобы обработчик события FormLoad
обновлял начальный атрибут Text YearComboBox из переменной года, определенной в SummaryForm, выполнял вызовы CreateCells()
для каждой строки, а затем вызывал отдельную функцию void для выполнения заполнения. Однако при отладке отдельная функция немедленно достигала бы первого оператора JanuaryRow, пытающегося отредактировать ячейку, и сообщала бы, что индекс равен -1 и, следовательно, выходит за пределы допустимого диапазона. Я попытался просто запустить событие SelectedValueChanged для обработчика событий FormLoad
, но это тоже не сработало из-за того, что строка уже была создана и заполнена.
Итак, мой вопрос: как я могу просто получить этот раскрывающийся список, чтобы изменить год, используемый операторами в обработчике событий FormLoad
(который отлично работает), и повторно заполнить DataGridView новыми значениями на основе обновленного года?
Я рад, что вы нашли решение, но я должен спросить, есть ли причина, по которой вы хотите, чтобы код повторно собирал данные каждый раз, когда пользователь меняет год? Неизвестно, сколько лет находится в поле со списком, но сбор всех данных за годы ОДИН РАЗ и сохранение их в контейнере, таком как DataSet
или List<T>
, кажется лучшим подходом. Ручное добавление столбцов и строк в сетку при каждом изменении в поле со списком просто кажется излишним, когда вы можете вернуть контейнер, используя свой текущий код… вместо того, чтобы записывать в сетку, записывайте в DataTable
и сохраняйте его… просто предложение. Удачи.
@JohnG В программе всего два года, 2020 и 2021. На 2021 год пока нет данных. Данные хранятся в DataSet, который взаимодействует с установленным SQL Server, на котором хранится вся информация. Переключение между годами — довольно редкое явление для пользователя, обычно они просто хотят загрузить текущий год, который загружается в обработчике событий FormLoad. Иногда пользователь может захотеть вернуться к предыдущему году, просто чтобы посмотреть на рост или сезонные тенденции. Как единственный пользователь этой программы, она работает по мере необходимости таким образом.
@JohnG Кроме того, чтобы было ясно, строки создаются и добавляются только один раз в обработчике событий FormLoad. В ответе на мой вопрос, который я опубликовал, я узнал, как просто редактировать ячейки DataGridView непосредственно в отдельном методе, который вызывается обработчиком событий поля со списком, и это решило мою проблему.
Ну, кажется, я наткнулся на решение, пробуя разные вещи. Может быть, не самая элегантная, но вот моя реализация PopulateSummaryGrid() на случай, если кто-то еще столкнется с этой проблемой:
// populate the summary data grid
private void PopulateSummaryDataGrid()
{
// update January row
SummaryDataGrid.Rows[0].Cells[1].Value = MainFormInstance.BillsOfSaleCountMonth(1, year);
SummaryDataGrid.Rows[0].Cells[2].Value = MainFormInstance.BillsOfSaleCashMonth(1, year);
SummaryDataGrid.Rows[0].Cells[3].Value = MainFormInstance.BillsOfSaleCreditMonth(1, year);
SummaryDataGrid.Rows[0].Cells[4].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[2].Value) + Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[3].Value);
SummaryDataGrid.Rows[0].Cells[5].Value = MainFormInstance.CashMonth(1, year);
SummaryDataGrid.Rows[0].Cells[6].Value = MainFormInstance.CardMonth(1, year);
SummaryDataGrid.Rows[0].Cells[7].Value = MainFormInstance.MonthCP(1, year);
SummaryDataGrid.Rows[0].Cells[8].Value = MainFormInstance.ExpensesMonthCP(1, year) + MainFormInstance.BillsOfSaleCashMonth(1, year);
SummaryDataGrid.Rows[0].Cells[9].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[7].Value) - Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[8].Value);
SummaryDataGrid.Rows[0].Cells[10].Value = MainFormInstance.MonthCF(1, year);
SummaryDataGrid.Rows[0].Cells[11].Value = MainFormInstance.ExpensesMonthCF(1, year);
SummaryDataGrid.Rows[0].Cells[12].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[10].Value) - Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[11].Value);
SummaryDataGrid.Rows[0].Cells[13].Value = MainFormInstance.ExpensesMonthGeneral(1, year);
SummaryDataGrid.Rows[0].Cells[14].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[5].Value) + Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[6].Value);
SummaryDataGrid.Rows[0].Cells[15].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[8].Value) + Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[11].Value) + Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[13].Value);
SummaryDataGrid.Rows[0].Cells[16].Value = Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[14].Value) - Convert.ToDecimal(SummaryDataGrid.Rows[0].Cells[15].Value);
...
SummaryDataGrid.Refresh();
}
Мне также пришлось удалить первый оператор моего обработчика событий FormLoad, который устанавливал текст YearComboBox в текущий год. Это, кажется, все работает правильно.
Я рад слышать, что ваша проблема решена, вы можете нажать «✔», чтобы отметить свой ответ как ответ.
Вы пробовали очистить свой datagriview? SummaryDataGrid.Rows.Clear(); СводкаДанных.Обновить(); также вы можете извлечь коды, которые добавляют строки в datagridview к методу вместо того, чтобы делать это при загрузке