#c# #winforms #data-binding #combobox
#c# #winforms #привязка данных #выпадающий список
Вопрос:
.NET 4.7.2 Winforms c#
Есть форма с кучей выпадающих списков. Выпадающий список для всех. Выпадающие списки заполняются либо из таблиц данных, либо из словарей. Они привязаны к столбцам в таблице данных для набора данных.
Выпадающие списки заполняются и привязываются к данным следующим образом:
dSDO = new Dictionary<bool, string>
{
{true,"Yes" },
{false,"No" }
};
CB1.DataSource = new BindingSource(dSDO, null);;
CB1.DisplayMember = "Value";
CB1.ValueMember = "Key";
CB2.DataSource = _dtCommodity;
CB2.DisplayMember = "CommodityAbbr";
CB2.ValueMember = "CommodityID";
// Databindings tried both before and after
CB1.DataBindings.Add("SelectedValue", dataset, "Tablename.colname1", true, DataSourceUpdateMode.OnPropertyChanged);
CB1.DataBindings.Add("SelectedValue", dataset, 'Tablename.colname2", true, DataSourceUpdateMode.OnPropertyChanged);
Выбор другого элемента в выпадающем списке обновляет столбец в строке данных. Однако состояние строки остается неизменным, и обновление для строки не происходит. Явный вызов ValidateChildren для формы ничего не делает.
Этот код использовался для работы в более старых платформах .NET (4.0 и старше); кажется, что что-то изменилось, чтобы прервать обработку, или я что-то упустил, и Microsoft больше не так снисходительна.
Есть идеи?
Спасибо!
Комментарии:
1. Вызывали ли вы
dataset.AcceptChanges();
после загрузки данных (чтобы установить статус для всех строкUnchanged
)? Кроме того, я бы использовал BindingSource для обработки набора данных (установите DataSet в качестве источника данных) и используйте BindingSource для привязки ComboBox (установитеDataSource
член привязки к BindingSource). Привязка к вложенному объекту будет работать таким образом. Статус строки будетModified
, когда вы зафиксируете значение через выпадающий список. Источником данных ComboBox должен быть объект, который реализуетINotifyPropertyChanged
(там нетListChanged
событий).2. Я не вызываю AcceptChanges — это установило бы статус без изменений. Я немедленно попробую это предложение.
3. При первой загрузке данных вы должны установить статус на
Unchanged
, в противном случае он останетсяAdded
, что неверно. У DataAdapter есть свойство,[DataAdapter].AcceptChangesDuringFill
, которое используется именно для этого.4. Моя проблема в том, что после изменения данных все еще отображается без изменений. Я меняю выделение в выпадающем списке, новое выбранное значение в выпадающем списке записывается в DataRow, но состояние строки остается неизменным. Изменение привязки данных полей к источнику привязки над набором данных не принесло никакой пользы. Тот же результат.
5. Затем добавьте BindingSource в качестве поля (например,
internal BindingSource bsDataSet = null;
)bsDataSet = new BindingSource(dataset, null); CB1.DataBindings.Add("SelectedValue", bsDataSet, "Tablename.colname1", true, DataSourceUpdateMode.OnPropertyChanged);
. Конечно, вы добавляете только одинDataBinding
, если вы попытаетесь добавить второй, вы получите исключение. Кстати, всегда устанавливайтеDisplayMember
иValueMember
(в этом порядке) передDataSource
.
Ответ №1:
Я нашел решение.
В соответствии с предложением от @Jimi я изменил код…
bsDataSource = new BindingSource(dataSet, "[SqlTableName]");
CB1.DataBindings.Add("SelectedValue", bsDataSource, "colname1", true, DataSourceUpdateMode.OnPropertyChanged);
CB2.DataBindings.Add("SelectedValue", bsDataSource, "colname2", true, DataSourceUpdateMode.OnPropertyChanged);
А затем при сохранении я сделал это:
using (SqlDataAdapter da = new SqlDataAdapter(SqlCommandObject))
{
using (SqlCommandBuilder cb = new SqlCommandBuilder(da))
{
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
cb.ConflictOption = ConflictOption.OverwriteChanges;
cb.SetAllValues = false;
da.InsertCommand = cb.GetInsertCommand(true);
da.UpdateCommand = cb.GetUpdateCommand(true);
da.DeleteCommand = cb.GetDeleteCommand(true);
try
{
// I Added this line
((DataRowView)bsDataSource.Current).EndEdit();
// End of what I added
da.MissingMappingAction = MissingMappingAction.Passthrough;
iRowCount = da.Update(ds, ds.Tables[0].TableName);
}
catch (Exception ex)
{
// [error handling]
}
}
}
Это привело к изменению состояния строки на измененное и успешному обновлению набора данных.
Итак, решение:
- Создайте BindingSource поверх объекта DataSet с именем таблицы соответствующей таблицы данных в качестве параметра 2
- Привязка каждого элемента управления к соответствующему имени столбца и указание источника привязки.
- Выполните EndEdit() над DataRowView, который находится в текущем свойстве.
- Затем выполните обновление DataAdapter.
Спасибо — Надеюсь, что это поможет кому-то еще.