C # обновление текстового поля из BindingSource - PullRequest
3 голосов
/ 28 октября 2008

У меня возникают проблемы при обновлении элементов управления форм 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
    }
}

Мы пытаемся связать каждую из трех таблиц DataTable с набором текстовых ящиков 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.

Вот наша проблема. Если мы выберем другой ключ ссуды и сделаем тот же вызов службе и получим новый DataSet, снова с 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.

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

Уэс

Ответы [ 5 ]

2 голосов
/ 20 января 2011

У меня была похожая проблема сегодня, и я нашел эту работу.

private void btnCancel_Click(object sender, EventArgs e)
{
    this.MyTable.RejectChanges();
    this.txtMyBoundTextBox.DataBindings[0].ReadValue();
    this.EditState = EditStates.NotEditting;
}
1 голос
/ 05 ноября 2008

Первое: этот пост нуждается в организации. Пиз помните, что ответы не в порядке. Порядок определяется путем голосования.

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

Ответы Upvote, которые вы считаете полезными.

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

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

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

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

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

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

0 голосов
/ 03 мая 2013

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

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

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

0 голосов
/ 29 октября 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, а также методом проб и ошибок. Это было довольно больно. Надеемся, что кто-то другой может добавить полезную ссылку или две.

0 голосов
/ 29 октября 2008

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

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

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

...