Поскольку этот вопрос все еще остается вопросом для некоторых, в том числе для меня, еще несколько дней назад, я решил опубликовать свое решение, и то, которое я преподаю учащимся в моих классах, начиная с этого момента:
Сначала я создаю объект DataGridView
(DGV) и создаю столбцы в режиме конструктора, принимая к сведению имя объекта для конкретного столбца.
Теперь, когда я хочу связать данные из моей базы данных (SQL Server, для этого кода). Я изменяю объекты столбца и привязываю каждый столбец непосредственно к данным из DataTable
.
private void FillAddresses()
{
// erase any old data
if (AddrTable != null)
AddrTable.Clear();
else
AddrTable = new DataTable();
// switch-case for panel types that need an address
switch(PanelType)
{
case "Customer":
case "Customers":
case "Location":
case "Locations":
case "Employee":
case "Employees":
BuildStateColumnChoices();
SqlCommand sqlAddrCmd = new SqlCommand();
sqlAddrCmd.CommandText = "exec SecSchema.sp_GetAddress " + PanelType +
"," + ObjectID.ToString(); // Fill the DataTable with a stored procedure
sqlAddrCmd.Connection = DBConnection;
sqlAddrCmd.CommandType = CommandType.Text;
SqlDataAdapter sqlDA = new SqlDataAdapter(sqlAddrCmd);
try
{
sqlDA.Fill(AddrTable);
dgvAddresses.AutoGenerateColumns = false;
// Actually, you set both the DataSource and DataPropertyName properties to bind the data
dgvAddresses.DataSource = AddrTable;
// Note that the column parameters are using the name of the object from the designer.
// This differs from the column names.
// The DataProperty name is set to the column name returned from the Stored Procedure
dgvAddresses.Columns["colAddrType"].DataPropertyName = "Type";
dgvAddresses.Columns["collAddress"].DataPropertyName = "Address";
dgvAddresses.Columns["colAptNum"].DataPropertyName = "Apt#";
dgvAddresses.Columns["colCity"].DataPropertyName = "city";
dgvAddresses.Columns["colState"].DataPropertyName = "State";
dgvAddresses.Columns["colZIP"].DataPropertyName = "ZIP Code";
}
catch(Exception errUnk)
{
MessageBox.Show("Failed to load address data for panel type " +
PanelType + "..." + errUnk.Message, "Address error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
break;
}
}
Для приведенного выше кода DBConnection является открытым свойством для объекта, из которого я взял этот код, в котором хранится объект SqlConnection
. Кроме того, colAddressType был столбцом ComboBox. Данные из привязанного DataTable
могут соответствовать только сведениям, перечисленным в ComboBox. Аналогично, colState является столбцом ComboBox, но значения по умолчанию для этого поля добавляются путем запроса другой таблицы, содержащей все состояния (в США, например, для этого примера).
Суть в том, что вы можете связать данные, которые вы хотите включить в DGV, создавая столбцы во время разработки, а затем связывая ваши данные из таблицы DataTable непосредственно со столбцами. Это позволяет вам иметь любой тип столбца, который вы хотите, а не просто TextColumn по умолчанию, который предоставляется вам механизмом привязки по умолчанию.
Следует отметить, что в этом случае DataTable является результатом хранимой процедуры и что редактирование в этом случае маловероятно. Я пытался использовать вид, а также сохраненную функцию; первое не разрешало редактирование (по крайней мере, не легко ... я подозреваю, что мне нужно было вставить что-то перед триггером, но это вопрос базы данных), в то время как второе не вернет таблицу на основании некоторой проблемы с динамическим генерация таблицы.