С# обновление текстового поля из BindingSource

У меня возникают трудности с обновлением элементов управления форм Windows, использующих объект BindingSource. У нас есть клиент CAB/MVP/SCSF, который я (на самом деле «мы», поскольку это работа команды) разрабатываю, который будет взаимодействовать со службами WCF, работающими на удаленном сервере. (Это наша первая попытка, поэтому мы находимся в режиме обучения). Один из вызовов (от презентатора) к службе возвращает набор данных, который содержит 3 таблицы данных с именами «Контракт», «Ссуда» и «Условия». Каждая таблица содержит только одну строку. Когда служба возвращает набор данных, мы сохраняем его в SmartPart/View в переменной-члене класса, вызывая в представлении функцию BindData() и передавая набор данных в представление из класса презентатора;

private System.Data.DataSet _ds = null;
public void BindData(System.Data.DataSet ds)
{
    string sErr = "";
    try
    {
        _ds = ds;  // save to private member variable

        // more code goes down here
    }
}

Мы пытаемся связать каждый из трех DataTables с набором текстовых полей Windows Forms, MaskedEditBox и раскрывающихся списков Infragistics UltraComboEditor. Мы создали три объекта BindingSource, по одному для каждого DataTable, используя IDE VS2008.

private System.Windows.Forms.BindingSource bindsrcContract;
private System.Windows.Forms.BindingSource bindsrcLoan;
private System.Windows.Forms.BindingSource bindsrcTerms;

Мы привязываем такие значения

if (bindsrcContract.DataSource == null)
{
    bindsrcContract.DataSource = _ds;
    bindsrcContract.DataMember = “contract”;

    txtContract.DataBindings.Add(new Binding("Text", bindsrcContract, "contract_id", true));                       

    txtLateFeeAmt.DataBindings.Add(new Binding("Text", bindsrcContract, "fee_code", true));

    txtPrePayPenalty.DataBindings.Add(new Binding("Text", bindsrcContract, "prepay_penalty", true));

    txtLateFeeDays.DataBindings.Add(new Binding("Text", bindsrcContract, "late_days", true));
}

if (bindsrcLoan.DataSource == null)
{
    bindsrcLoan.DataSource = _ds;
    bindsrcLoan.DataMember = “loan”;

    mskRecvDate.DataBindings.Add(new Binding("Text", bindsrcLoan, "receive_date", true));

    cmboDocsRcvd.DataBindings.Add(new Binding("Value", bindsrcLoan, "docs", true));     
}

Это работает, когда мы делаем первое чтение из службы и возвращаем набор данных. Информация отображается в элементах управления формы, мы можем обновить ее с помощью формы, а затем «сохранить», передав измененные значения обратно в службу WCF.

Вот наша проблема. Если мы выберем другой ключ кредита и сделаем тот же вызов службы и получим новый набор данных, опять же с 3 таблицами с одной строкой в ​​каждой, элементы управления (текстовые поля, маскированные поля редактирования и т. д.) не будут обновляться с новой информацией . Обратите внимание, что smartPart/View не закрывается или что-то еще, а остается загруженным между вызовами службы. При втором вызове мы не перепривязываем вызовы, а просто пытаемся обновить данные из обновленного набора данных.

Мы перепробовали все, что могли придумать, но явно чего-то не хватает. Это наша первая попытка использовать элемент управления BindingSource. мы пробовали

bindsrcContract.ResetBindings(false);

и

bindsrcContract.ResetBindings(true);

и

bindsrcContract.RaiseListChangedEvents = true;

и

for (int i = 0; i < bindsrcContract.Count; i++)
{
    bindsrcContract.ResetItem(i);
}

А также повторный сброс свойства DataMember.

bindsrcContract.DataMember = ”Contract”;

Мы рассмотрели множество примеров. Многие примеры ссылаются на BindingNavigator, но, поскольку DataTables имеют только одну строку, мы не думали, что нам это нужно. Есть много примеров для сеток, но мы не используем их здесь. Может ли кто-нибудь указать, где мы ошибаемся, или указать нам ресурсы, которые предоставят дополнительную информацию?

Мы используем VisualStudio 2008, C# и .Net 2.0, клиент XP, сервер W2K3.

заранее спасибо

Уэс


person Community    schedule 28.10.2008    source источник


Ответы (5)


Сегодня у меня была аналогичная проблема, и я нашел, что это работает.

private void btnCancel_Click(object sender, EventArgs e)
{
    this.MyTable.RejectChanges();
    this.txtMyBoundTextBox.DataBindings[0].ReadValue();
    this.EditState = EditStates.NotEditting;
}
person Jimmy V    schedule 19.01.2011

Во-первых, этот пост нужно упорядочить. Пожалуйста, помните, что ответы не хранятся в порядке. Порядок определяется голосованием.

Поэтому, если у вас есть дополнительные вопросы, просто измените исходный вопрос (отметьте "Изменить", чтобы избежать путаницы).

Проголосуйте за ответы, которые вы считаете полезными.

Да, кстати, используйте кнопку с образцами кода (над окном редактирования) при добавлении образцов кода. Это даст вам хорошее форматирование кода, включая подсветку синтаксиса.

Теперь к сути: основная проблема в обоих ваших вопросах заключается в том, что Binding-Manager сохраняет ссылки на исходные объекты.

Когда вы назначаете _ds в качестве источника данных, Binding-Manager анализирует набор данных и действует соответствующим образом. Если вы назначите какой-либо другой набор данных для _ds, Binding-Manager не сможет узнать об этом. Он по-прежнему имеет ссылку на исходный объект DataSet. Таким образом, это объясняет, почему вы должны сбросить свойство DataSource на новый DataSet.

Это также объясняет, почему удаление и добавление таблицы не приводит к ожидаемому результату. Опять же, Binding-Manager содержит ссылку на старую таблицу (или первую строку в этой таблице). Новая таблица никогда не привязывается. Также в этом случае переназначение _ds не помогает, так как _ds указывает на тот же объект DataSet, что и раньше. Binding-Manager достаточно умен, чтобы заметить, что это один и тот же объект и не выполняет перепривязку.

Вам либо нужно изменить содержимое ваших связанных объектов (которое запускает событие PropertyChanged-Event, на которое подписывается Binding-Manager), либо вам нужно инициировать полную повторную привязку, назначив другой объект свойству DataSource.

Это упрощенное описание того, что происходит на самом деле, но я надеюсь, что этого достаточно, чтобы объяснить и решить вашу проблему. К сожалению, мне еще предстоит найти исчерпывающее объяснение привязки данных WinForms в Интернете (или где-либо еще).

person TToni    schedule 05.11.2008
comment
TToni, спасибо за полезное объяснение. Кстати, ОП не может проголосовать за 11 (или 1 после перерегистрации) очков репутации;) - person Alan; 06.11.2008

В противном случае вы можете переназначать DataSource каждый раз, когда получаете новый набор данных, делая что-то вроде этого:

bindsrcContract.DataSource = typeof(System.Data.DataSet);
bindsrcContract.DataSource = _ds;

(Кроме того, инициализация сначала DataMember, а затем DataSource повысит производительность.)

person Alan    schedule 28.10.2008

Уэс, я очень рад, что смог помочь. Я до сих пор помню проблему, очень похожую на вашу, на решение которой у меня ушло несколько недель...

Что касается ваших вопросов, вот все, что я знаю:

  1. Если вы сначала установите DataSource, а затем DataMember, ваш источник данных будет сканироваться дважды, поскольку установка DataMember впоследствии изменяет существующую (действительную) привязку. Если вы делаете это наоборот, сначала устанавливая DataMember (с DataSource равным нулю или лучше, typeof(YourData)), привязка происходит только один раз, когда вы устанавливаете DataSource.

  2. Я думаю, вы можете применить то же решение здесь. Вместо того, чтобы просто

    bindsrcContract.DataSource = _ds;
    

    в вашей последней строке вы должны написать

    bindsrcContract.DataSource = typeof(System.Data.DataSet);
    bindsrcContract.DataSource = _ds;
    
  3. Извините, что разочаровываю, но все, что я знаю о привязке данных, я узнал из MSDN, а также методом проб и ошибок. Это было довольно болезненно. Надеюсь, кто-то еще может присоединиться с полезной ссылкой или двумя.

person Alan    schedule 29.10.2008

попробуйте комбинацию:

bindingsource.EndEdit() // writting data to underlying source 
bindingSource.ResetBindings(false)  // force controls to reread data from bindingSource

используйте это всякий раз, когда вы пишете что-то в элементы управления.

person zeljko    schedule 02.05.2013