2008-10-28 3 views
3

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

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 TextBoxes, MaskedEditBoxes и Infragistics UltraComboEditor DropDown ComboBoxes Мы создали три объекта BindingSource, по одному для каждого DataTable с помощью VS2008 IDE.

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

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

bindsrcContract.ResetBindings(false); 

и

bindsrcContract.ResetBindings(true); 

и

bindsrcContract.RaiseListChangedEvents = true; 

и

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

Как и снова сбросить свойство DataMember.

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

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

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

Wes

ответ

0

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

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

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

0

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

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

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

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

    bindsrcContract.DataSource = _ds; 
    

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

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

1

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

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

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

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

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

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

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

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

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

+0

TToni, спасибо за полезное объяснение. BTW, OP не может повышать ставку на 11 (или 1 после перерегистрации) точек репутации;) – Alan

2

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

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

сочетание попробовать:

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

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

Смежные вопросы