Я предполагаю, что может быть лучший способ сделать это, однако, учитывая то, что я могу расшифровать, будет go что-то вроде ...
Есть множество ComboBoxes
выше DataGridView
. Каждый из столбцов сетки соответствует определенному ComboBox
. Если пользователь нажимает на строку в сетке, соответствующие поля со списком должны быть установлены на те же значения, которые находятся в «выбранной» строке в сетке. Кроме того, после того, как пользователь «выберет» строку в сетке и поля со списком заполнятся данными о «этих» строках, ТО ... затем пользователь может «изменить» некоторые значения в полях со списком, а затем нажать кнопку «Сохранить» сохранить выбранные значения поля со списком в «выбранную» строку в сетке. Кроме того, эти изменения также должны быть обновлены в базе данных. Я надеюсь, что у меня есть это право.
Это много для вопроса о SO, и я постараюсь помочь разбить часть его на управляемые кусочки.
Ниже приведен рисунок формы код ниже управляет. Есть форма с сохранением Button
, пятью (5) ComboBoxes
и DataGridView
. Используется таблица базы данных (TestCombos), которая имеет следующую схему…
RecordNumber int PrimaryKey – not null
Member nvarchar(50) - null
Ward nvarchar(50) - null
Deficit int - null
Reason nvarchar(50) - null
Band nvarchar(50) - null
![enter image description here](https://i.stack.imgur.com/my1pI.jpg)
Из вашего опубликованного кода я не вижу « где »код« Обновление »базы данных с изменениями выбранной строки. Метод LoadDataToQuery
кажется (неловко) «вставить» «новую» строку из поля со списком. Бьюсь об заклад, причина, по которой код «обновления» отсутствует, заключается в том, что из того, что я вижу в коде… Как бы вы ЗНАЛИ «какую» строку в таблице базы данных «обновить»? Другими словами, если пользователь «выбрал» строку, изменил поля со списком, а затем нажал кнопку «Сохранить». Мы бы знали, какая «строка» изменилась, поскольку она является выбранной строкой в сетке, и из нее мы могли бы получить, какую строку выбрать в сетках DataSource
DataTable
… однако мы не обязательно ЗНАЛИ, какая строка в таблица базы данных для обновления.
Я не вижу ничего «уникального», которое бы идентифицировало одну строку из другой. Я вижу, как используется «Дата», но я также могу представить множество строк с одной и той же датой. Указывайте, что вам нужен какой-то уникальный идентификатор, чтобы указать на соответствующую строку в таблице базы данных. Вот почему я добавил столбец «RecordNumber» в таблицу и сделал его первичным ключом без нулей и, очевидно, без дубликатов. Таким образом, когда коду необходимо «обновить» запись в таблице базы данных, мы будем точно знать, какая именно.
Нет необходимости показывать этот столбец пользователю, однако вам потребуется убедитесь, что при добавлении «Новой» записи / строки, RecordNumber
уникален. В этом примере код просто использует номер строки в таблице в качестве номера записи, если пользователь «добавляет» строку, RecordNumber
для этой строки будет количеством строк в таблице + 1. Это будет работать для этот пример; Однако я НЕ рекомендую использовать эту стратегию. Если вы «удалите» строки, это вызовет проблемы. Поэтому я рекомендую другой подход для получения уникального ключа для новых строк.
Наличие каждой строки с уникальным ключом значительно упростит «обновление» значений в таблице базы данных и станет менее подверженным ошибкам при использовании предложения WHERE. в запросе, чтобы определить правильную строку для обновления.
Еще одна вещь, отсутствующая в вашем посте, это «какие» значения вы добавляете в поля со списком? Странное событие RowHeaderMouseClick
появляется, чтобы ... захватить выбранный row
, а затем вывести некоторые сообщения из ячеек выбранной строки. Тогда по неизвестным причинам ВСЕ поля со списком очищаются от предметов? ПОЧЕМУ? … Затем ячейки выбранной строки «добавляются» в соответствующие элементы комбинированного списка? … По сути, каждый раз, когда пользователь щелкает заголовок строки, любое значение в поле со списком удаляется, а значения ячеек выбранных строк в сетке добавляются в поля со списком. Это будет означать, что поля со списком будут иметь только ОДНО значение (1), и пользователь никогда не увидит поле со списком со «множественными» значениями.
Неизвестно, хотите ли вы, чтобы пользователь мог «добавлять» элементы в поля со списком, и «обычно» поля со списком имеют ИСПРАВЛЕННЫЕ значения, которые не изменяются; Тем не менее, я видел ситуации, когда элементы должны быть добавлены в поле со списком. К сожалению, этот пример НЕ позволяет пользователю «добавлять» новые элементы.
Учитывая это, я предполагаю, что вы хотите, чтобы комбинированные блоки содержали… «ВСЕ уникальные значения для соответствующего столбца в сетке» , Например, в поле со списком «Сотрудник» вы должны указать ВСЕ «разные» значения Сотрудника в таблице без дубликатов. Если вам известен заранее определенный набор значений, которые вы хотите использовать, вы можете сначала добавить эти значения. Однако возможно, что в данных МОЖЕТ быть значение, которое НЕ является одним из предопределенных значений. Эти значения НЕ будут отображаться в поле со списком, если вы не добавите их.
Поэтому, чтобы «почти» гарантировать, что ВСЕ значения находятся в поле со списком, сначала необходимо добавить предварительно определенные значения, а затем проверить данные для любых значений, которые НЕ являются частью предварительно определенных значений. Если вы найдете его, добавьте его в поле со списком, так же как и в данных. В этом примере НЕТ предопределенных значений для полей со списком. Код просто перебирает данные и извлекает уникальные / уникальные значения из каждого столбца.
Вы можете запросить базу данных для этих данных, однако нижеприведенный метод GetUniqueDataFromSource(colIndex As Int32, dt As DataTable, type As Int32)
- это простой метод, который принимает столбец индекс для определения того, какой столбец данных мы хотим получить, DataTable
, который содержит данные, и значение int для определения «типа» списка, который мы хотим вернуть, либо строковый, либо int.
Сначала «Тип» проверяется и создается новый список. Ноль (0) и пустая строка добавляются в поля со списком, чтобы облегчить добавление новых строк. Простое l oop через строки таблицы данных, чтобы добавить каждый элемент в список. Если список уже «содержит» это значение, оно НЕ добавляется в список (Дублировать). Наконец список сортируется и затем возвращается. Этот метод будет использоваться для установки каждого поля со списком DataSource
на соответствующие значения для соответствующего столбца в сетке и будет называться ONCE для каждого поля со списком при загрузке формы.
Private Function GetUniqueDataFromSource(colIndex As Int32, dt As DataTable, type As Int32)
Dim dataList
If (type = 2) Then
dataList = New List(Of Int32)
dataList.Add(0)
Else
dataList = New List(Of String)
dataList.Add("")
End If
Dim curItem
For Each row As DataRow In dt.Rows
curItem = row.ItemArray(colIndex)
If (Not dataList.Contains(curItem)) Then
dataList.Add(curItem)
End If
Next
dataList.Sort()
Return dataList
End Function
Это должно « заполните »поля со списком правильными данными. Однако, если пользователь выбирает строку, поля со списком не будут отражать значения из «выбранной» строки. Чтобы помочь, метод с именем UpdateCombosFromGrid()
может быть полезным. Этот метод не принимает аргументов и просто устанавливает значение каждого поля со списком равным значению из текущей «выбранной» строки. Код проверяет, есть ли выбранная строка, а затем устанавливает соответствующее поле со списком с соответствующим значением и типом из сетки. Имейте в виду, что сетка SelectionMode
ДОЛЖНА быть установлена на «полный ряд». В противном случае DataGridView1.SelectedRows.Count
всегда будет возвращать ноль (0).
Private Sub UpdateCombosFromGrid()
If (DataGridView1.SelectedRows.Count > 0) Then
Dim selectedRow = DataGridView1.SelectedRows(0)
Dim value = 0
ComboBox1.SelectedItem = selectedRow.Cells("Member").Value
ComboBox2.SelectedItem = selectedRow.Cells("Ward").Value
Integer.TryParse(selectedRow.Cells("Deficit").Value.ToString(), value)
ComboBox3.SelectedItem = value
ComboBox4.SelectedItem = selectedRow.Cells("Reason").Value
ComboBox5.SelectedItem = selectedRow.Cells("Band").Value
End If
End Sub
Мы можем использовать вышеописанный метод для установки значений поля со списком, когда форма загружается, а также когда пользователь меняет выбор сетки. Если пользователь выбирает другую строку, то поля со списком будут отражать это изменение. Однако, если пользователь выбирает строку «Новая», последнюю «пустую» строку в сетке, как показано на рисунке, то мы хотим «очистить» поля со списком. Это не действительно необходимо; однако, это было бы хорошим сигналом для пользователя, что они МОГУТ ДОБАВЛЯТЬ новые строки. Если выбранная строка НЕ является новой строкой, вызовите вышеуказанный метод.
Private Sub DataGridView1_SelectionChanged(sender As Object, e As EventArgs) Handles DataGridView1.SelectionChanged
If (DataGridView1.SelectedRows.Count > 0) Then
Dim selectedRow = DataGridView1.SelectedRows(0)
If (selectedRow.IsNewRow) Then
ComboBox1.SelectedItem = ""
ComboBox2.SelectedItem = ""
ComboBox3.SelectedItem = 0
ComboBox4.SelectedItem = ""
ComboBox5.SelectedItem = ""
Else
UpdateCombosFromGrid()
End If
End If
End Sub
Это должно обеспечить обновление полей со списком, чтобы они отражали «выбранную» строку сетки, когда пользователь выбирает другие строки.
Далее следует кнопка «Сохранить», и она действительно должна сделать две вещи: сначала нам нужно «обновить» «выбранную» строку в сетке И также «обновить» эту строку в базе данных. Чтобы помочь, метод, который делает обратный метод UpdateCombosFromGrid()
. Как следует из названия, метод UpdateSelectedRowFromCombos()
получает значения из полей со списком и устанавливает эти значения в «выбранную» строку в сетке.
Private Sub UpdateSelectedRowFromCombos()
If (DataGridView1.SelectedRows.Count > 0) Then
Dim selectedRow = DataGridView1.SelectedRows(0)
Dim value = 0
selectedRow.Cells("Member").Value = ComboBox1.SelectedValue
selectedRow.Cells("Ward").Value = ComboBox2.SelectedValue
Integer.TryParse(ComboBox3.SelectedValue, value)
selectedRow.Cells("Deficit").Value = value
selectedRow.Cells("Reason").Value = ComboBox4.SelectedValue
selectedRow.Cells("Band").Value = ComboBox5.SelectedValue
End If
End Sub
Это позаботится о получении новых значений в сетке, будь то обновление существующей строки или добавление новой строки. Однако «обновление» строки в таблице базы данных и «добавление» строки - это два разных запроса. Я уверен, что вы могли бы сделать один метод для этого, однако я сделаю два разных метода. Оба метода берут DataRow
и либо «обновляют» существующую строку, либо «вставляют» новую строку.
Private Sub UpdateDB_WithRow(rowToUpdate As DataRow)
Dim connString = "Server = localhost; Database = TestDB; Trusted_Connection = True;"
Using conn As SqlConnection = New SqlConnection(connString)
Dim cmd = New StringBuilder("UPDATE TestCombos SET Member = @Member, Ward = @Ward, ")
cmd.Append("Deficit = @Deficit, Reason = @Reason, Band = @Band ")
cmd.Append("WHERE RecordNumber = @RecordNumber")
conn.Open()
Using da As SqlDataAdapter = New SqlDataAdapter()
da.UpdateCommand = conn.CreateCommand()
da.UpdateCommand.Parameters.AddWithValue("@Member", rowToUpdate("Member"))
da.UpdateCommand.Parameters.AddWithValue("@Ward", rowToUpdate("Ward"))
da.UpdateCommand.Parameters.AddWithValue("@Deficit", rowToUpdate("Deficit"))
da.UpdateCommand.Parameters.AddWithValue("@Reason", rowToUpdate("Reason"))
da.UpdateCommand.Parameters.AddWithValue("@Band", rowToUpdate("Band"))
da.UpdateCommand.Parameters.AddWithValue("@RecordNumber", rowToUpdate("RecordNumber"))
da.UpdateCommand.CommandText = cmd.ToString()
da.UpdateCommand.ExecuteNonQuery()
End Using
End Using
End Sub
Вставляют новую строку…
Private Sub InsertNewRowToDB(rowToUpdate As DataRow)
Dim connString = "Server = localhost; Database = TestDB; Trusted_Connection = True;"
Using conn As SqlConnection = New SqlConnection(connString)
Dim cmd = New StringBuilder("INSERT INTO TestCombos Values (@RecordNumber, @Member, @Ward, @Deficit, @Reason, @Band)")
conn.Open()
Using da As SqlDataAdapter = New SqlDataAdapter()
da.InsertCommand = conn.CreateCommand()
da.InsertCommand.Parameters.AddWithValue("@Member", rowToUpdate("Member"))
da.InsertCommand.Parameters.AddWithValue("@Ward", rowToUpdate("Ward"))
da.InsertCommand.Parameters.AddWithValue("@Deficit", rowToUpdate("Deficit"))
da.InsertCommand.Parameters.AddWithValue("@Reason", rowToUpdate("Reason"))
da.InsertCommand.Parameters.AddWithValue("@Band", rowToUpdate("Band"))
da.InsertCommand.Parameters.AddWithValue("@RecordNumber", rowToUpdate("RecordNumber"))
da.InsertCommand.CommandText = cmd.ToString()
da.InsertCommand.ExecuteNonQuery()
End Using
End Using
End Sub
С помощью метода для обновления Выбранная строка и метод для обновления / добавления строки в базу данных, событие сохранения может выглядеть примерно так: *
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim selectedRow = DataGridView1.SelectedRows(0)
Dim newRow
If (selectedRow.IsNewRow) Then
newRow = ds.Tables("TestCombos").Rows.Add()
newRow("RecordNumber") = ds.Tables("TestCombos").Rows.Count
newRow("Member") = ComboBox1.SelectedItem
newRow("Ward") = ComboBox2.SelectedItem
newRow("Deficit") = ComboBox3.SelectedItem
newRow("Reason") = ComboBox4.SelectedItem
newRow("Band") = ComboBox5.SelectedItem
DataGridView1.CurrentCell = DataGridView1.Rows(selectedRow.Index - 1).Cells(0)
InsertNewRowToDB(newRow)
Else
UpdateSelectedRowFromCombos()
Dim tableRowIndex = ds.Tables("TestCombos").Rows.IndexOf(DirectCast(selectedRow.DataBoundItem, DataRowView).Row)
UpdateDB_WithRow(ds.Tables("TestCombos").Rows(tableRowIndex))
End If
End Sub
Метод для получения данных из базы данных ...
Private Sub GetDataFromDB()
ds = New DataSet()
Dim connString = "Server = localhost; Database = TestDB; Trusted_Connection = True;"
Dim query = "select * from TestCombos"
Using conn = New SqlConnection(connString)
Dim cmd = New SqlCommand(query, conn)
conn.Open()
Dim da = New SqlDataAdapter(cmd)
da.Fill(ds, "TestCombos")
conn.Close()
End Using
End Sub
Далее нам нужен метод для установки значений каждого поля со списком после загрузки данных. Мы можем использовать метод GetUniqueDataFromSource
, описанный ранее, и он может выглядеть следующим образом…
Private Sub SetComboBoxValues()
ComboBox1.DataSource = GetUniqueDataFromSource(1, ds.Tables("TestCombos"), 1)
ComboBox2.DataSource = GetUniqueDataFromSource(2, ds.Tables("TestCombos"), 1)
ComboBox3.DataSource = GetUniqueDataFromSource(3, ds.Tables("TestCombos"), 2)
ComboBox4.DataSource = GetUniqueDataFromSource(4, ds.Tables("TestCombos"), 1)
ComboBox5.DataSource = GetUniqueDataFromSource(5, ds.Tables("TestCombos"), 1)
End Sub
Наконец, собрав все это вместе в событии загрузки формы…
Dim ds As DataSet
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetDataFromDB()
DataGridView1.DataSource = ds.Tables("TestCombos")
SetComboBoxValues()
UpdateCombosFromGrid()
DataGridView1.ReadOnly = True
End Sub
Я надеюсь, что это Помогите. И возможно сделать сетку заполненной полями со списком, однако это был бы другой вопрос. Удачи!