Обработайте или избегайте ошибки «Не удается привязаться к свойству или столбцу X в источнике данных» при изменении DS

#c# #winforms #data-binding

Вопрос:

Отказ от ответственности: Я не ищу причину проблемы, я ее еще знаю: исключение создается набором источника данных, у которого изначально есть поле (Table2.name2), привязанное к элементу управления (TextBox1.Text), но затем источник данных изменяется, и это поле больше недоступно.
Я хотел бы обсудить возможные решения и найти то, которое лучше подходит для моего случая.

Я создал приложение, которое имитирует поведение моего реального кода. Решение доступно в данный момент по адресу https://github.com/samuelecoassin/winforms-test-bindings. Я сообщаю здесь ниже основной код.

Приложение Winforms

 private void SetBindings()
{
    bs1.ResetBindings(false);
    bs1.DataMember = "Table1";
    bs1.DataSource = _ds;
    dgvOne.DataSource = bs1;

    bs2.ResetBindings(false);
    bs2.DataMember = "FK1";
    bs2.DataSource = bs1;
    dgvTwo.DataSource = bs2;

    textBox1.DataBindings.Add("Text", bs2, "name2", true, DataSourceUpdateMode.OnPropertyChanged);
}
 

Когда я нажимаю на кнопку своей программы, инициализируется источник данных _ds, а затем вызываются стандартные привязки.
Этот код вызывается, когда я нажимаю кнопку «Первый ds».:

 private void InitDataSet1()
{
    DataTable table1 = new DataTable("Table1");
    table1.Columns.Add("id1");
    table1.Columns.Add("name1");
    table1.Rows.Add(1, "Test A");
    table1.Rows.Add(2, "Test B");
    table1.Rows.Add(3, "Test C");

    DataTable table2 = new DataTable("Table2");
    table2.Columns.Add("id2");
    table2.Columns.Add("idTable1");
    table2.Columns.Add("name2");
    table2.Rows.Add(1, 1, "A - 1");
    table2.Rows.Add(2, 1, "A - 2");
    table2.Rows.Add(3, 2, "B - 3");
    table2.Rows.Add(4, 2, "B - 4");

    DataSet tempDs = new DataSet();
    tempDs.Tables.Add(table1);
    tempDs.Tables.Add(table2);
    tempDs.Relations.Add("FK1", table1.Columns["id1"], table2.Columns["idTable1"]);

    _ds = tempDs;

    SetBindings();
}
 

The code when I press button «Second ds» is similar, but only Table1 is loaded:

 private void InitDataSet2()
{
    DataTable table1 = new DataTable("Table1");
    table1.Columns.Add("id1");
    table1.Columns.Add("name1");
    table1.Rows.Add(1, "Test A");
    table1.Rows.Add(2, "Test B");
    table1.Rows.Add(3, "Test C");

    DataSet tempDs = new DataSet();
    tempDs.Tables.Add(table1);

    _ds = tempDs;

    SetBindings();
}   
 

That reproduces in a simple way the behavior of the real application: Table2 is shown in a tab, and it is loaded only if I focus the tab.
This allows to speed up the loading of the main data, as Table1. Note that Table1 and Table2 in reality could be more tables or views, so the time to load could be longer than seconds.

At the moment I found two solutions, both with some issues:

  • populate always the DataSet with the structure of Table2, and load data only if needed (focus on tab).
    The issue is that before the presence of Table2 indicated data was already loaded, now if there is structure I don’t know if I have to load data or I have already done it and I don’t have any records.
  • catch and ignore the exception.
    I found the routine Binding.OnBindingComplete that allows to intercept binding errors, but it doesn’t run in my case (when I change the data source).

Do you have any other solution to propose?

Thank you for your time and sorry for my imperfect english.