Я разрабатываю приложение формы Windows, управляющее базой данных SQL Server. Когда я щелкаю поле со списком, которое заполнено всеми таблицами, я добавляю все столбцы из выбранной таблицы в поле списка, а затем, когда я проверяю, чтобы следующий столбец исчез. Я застрял здесь.
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var tableName = comboBox1.SelectedItem;
SqlDataAdapter sqlDa = new SqlDataAdapter($"SELECT * FROM {tableName}", form1.conn = new SqlConnection($"Server = {form1.ServerBox.Text }; Database = { form1.DBBox.Text}; Trusted_Connection = True"));
DataTable dataTable = new DataTable();
sqlDa.Fill(dataTable);
string comboQuery = $"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'{tableName}'";
using (form1.conn = new SqlConnection($"Server = {form1.ServerBox.Text }; Database = { form1.DBBox.Text}; Trusted_Connection = True"))
{
form1.conn.Open();
using (SqlCommand cmd = new SqlCommand(comboQuery, form1.conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
checkedListBox1.Items.Clear();
while (reader.Read())
{
checkedListBox1.Items.Add((string)reader["COLUMN_NAME"]);
}
}
}
form1.conn.Close();
}
dataGridView1.DataSource = dataTable;
}
Спасибо, за потраченное время!





Вы можете начать с заполнения CheckedListBox, может быть, так:
checkedListBox1.Items.Clear
checkedListBox1.Items.AddRange(dataGridView1.Columns.Cast<DataGridViewColumn>()
.Select(x => x.Name)
.ToArray());
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
checkedListBox1.SetItemChecked(i, true);
}
checkedListBox1.CheckOnClick = true;
Теперь вы можете закодировать событие checkedListBox1_SelectedIndexChanged так:
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
dataGridView1.Columns[i].Visible =
checkedListBox1.GetItemCheckState(i) == CheckState.Checked;
}
Обновлять Реза нашел событие ItemCheck; не уверен, как я пропустил это ;-). Это, очевидно, намного лучше, так как не нужно просматривать все элементы.
Когда у вас есть столбцы в DataGridView, вам не нужно снова загружать их с сервера SQL, и, как уже показано в другом ответе, вы можете получить имена столбцов из DataGridView.
Чтобы добавить столбцы в CheckedListBox, я предпочитаю использовать DataSource, DisplayMember и ValueMember, чтобы показать столбец HeaderText в CheckedListBox, имея доступ к их именам, чтобы иметь возможность найти их в DataGridView.
Затем я бы установил начальное состояние проверки элементов на основе видимости соответствующего столбца.
Затем я обрабатываю событие ItemCheck и нахожу имя столбца на основе отмеченного элемента и устанавливаю видимость столбца на основе нового состояния проверки:
//Add the columns to checked list box
var columns = dataGridView1.Columns.Cast<DataGridViewColumn>()
.Select(x => new { x.Name, x.HeaderText }).ToList();
checkedListBox1.DataSource = columns;
checkedListBox1.ValueMember = "Name";
checkedListBox1.DisplayMember = "HeaderText";
//Set initial check state based on columns visibility
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
dynamic item = checkedListBox1.Items[i];
checkedListBox1.SetItemChecked(i, dataGridView1.Columns[(string)item.Name].Visible);
}
//Hanlde ItemCheck event
checkedListBox1.ItemCheck += (obj, args) =>
{
dynamic item = checkedListBox1.Items[args.Index];
var visible = args.NewValue == CheckState.Checked ? true : false;
dataGridView1.Columns[(string)item.Name].Visible = visible;
};
На всякий случай, если вам интересно сделать это, используя ContextMenuStrip:
//Add the columns to context menu strip
foreach (DataGridViewColumn c in dataGridView1.Columns)
{
var item = (ToolStripMenuItem)contextMenuStrip1.Items.Add(c.HeaderText);
item.Tag = c.Name;
item.Checked = c.Visible;
item.CheckOnClick = true;
//Hanlde CheckStateChanged event of context menu strip items
item.CheckStateChanged += (obj, args) =>
{
var i = (ToolStripMenuItem)obj;
dataGridView1.Columns[(string)i.Tag].Visible = i.Checked;
};
}
//Show context menu strip on right click on data grid veiw header
dataGridView1.CellMouseClick += (obj, args) =>
{
if (args.RowIndex == -1 && args.Button == MouseButtons.Right)
contextMenuStrip1.Show(Cursor.Position);
};
Если вы поместите код в Load обработчик событий вашей формы и у вас есть dataGridView1 и contextMenuStrip1, он будет работать правильно. Верно? Значит для dataGridView2, нужно contextMenuStrip2.
Ну, я сделал код таким образом, когда вы выбираете элемент из поля со списком таблицы, datagridview изменяется с выбранной таблицей. Но когда я выбираю другую таблицу, полосное меню из первого сохраняется, и у меня есть все значения в этом меню.
Я могу представить некоторые возможные ошибки в коде, но я не уверен в вашем коде. давайте оставим этот пост как есть (поскольку этот кусок кода является бесплатным для поста и не является основным ответом на ваш вопрос) и зададим новый вопрос, включая минимальный воспроизводимый пример, чтобы воспроизвести проблему и описать ожидаемое поведение, тогда я или, может быть, другой участник сообщества поможет вам решить проблему :)
Но когда я меняю значение на другую таблицу, все они сохраняются, и если у меня есть, например, в первой таблице «ID», а во втором «Имя» и «Номер», все они сохраняются в ToolStripMenu, и я только потребность в выбранной таблице.