Re: DataBindings.Add



Hi,

What looks suspicious is that you are trying to bind to a DataRow. This is unusual scenario. Usually one binds to a DataSet or a DataTable (in the former case, the property name must be specified as TableName.ColumnName), and an instance of CurrencyManager created behind the scenes will manage the current row for you.

--
Sincerely,
Dmytro Lapshyn [Visual Developer - Visual C# MVP]


"C Glenn" <nospam@xxxxxxxxxx> wrote in message news:Oq$Rt2h9FHA.600@xxxxxxxxxxxxxxxxxxxxxxx
This is admitedly vague. But so is my understanding of the problem. I'm using this chunk of code:

retControl.DataBindings.Add(ctrlBinding.PropertyName,DataSource[i],BindingField);

This resolves to something like:

Control.DataBindings.Add("Text", SomeDataTable.Rows[1], "Priority");

The only difference that I can see is that one of the DataSets is created by a DataAdapter through the IDE at design time while the second is instantiated dynamically at run time. In both cases they contain one DataTable.

When I attempt to accomplish the same task with the dynamcally instantiated Control it fails. In the code below you will see a line that calls the function DeepCloneControl. It never fails within DeepCloneControl. It always fails after it returns. DeepCloneControl begins by cloning a control. Then it loops through some of its properties recreating them in the clone. (Some are excluded.) Finally, it loops through its bindings recreating them in the clone. (This is where the problem is. If I comment this loop out, it succeeds.) Only after the function returns, without ever throwing an exception, does it fail on the line that called DeepCloneControl. This is the message

Cannot bind to property or column <field name> on DataSource.

Within DeepCloneControl you will notice this:
retControl.DataBindings.Add(ctrlBinding.PropertyName,
                            DataSource[i],BindingField);

DataSource[i] refers to an object returned by:
new DataRowCollectionSocket(DataSet.DataTable.Rows);

A DataRowCollectionSocket is defined by:
public interface IDataSocket
 {
  int Count{get;}
  object this[int index]{get;}
 }
public class DataRowCollectionSocket: IDataSocket
 {
  public System.Data.DataRowCollection Data;

  public DataRowCollectionSocket(System.Data.DataRowCollection data)
  {
   this.Data = data;
  }

 public int Count
  {
   get
   {
    return Data.Count;
   }
  }

 public object this[int index]
  {
   get
   {
    return Data[index];
   }
  }
 }

Here's the significant bit of code:

tempPanel.Controls.Add(DeepCloneControl(c,i));// This is where it fails.

public Control DeepCloneControl(Control subject, int i)
{
 Type ctrlType = subject.GetType();
 ConstructorInfo cInfo = ctrlType.GetConstructor(Type.EmptyTypes);
 Control retControl = (Control)cInfo.Invoke(null);

foreach(PropertyInfo pInfo in ctrlType.GetProperties(BindingFlags.Public|BindingFlags.Instance))
{
if (pInfo.CanWrite && (pInfo.PropertyType.IsValueType || pInfo.PropertyType.Name == "String"))
{
try
{
switch(pInfo.Name)
{
case "Parent":
break;
case "SelectionStart":
break;
case "SelectedText":
break;
case "SelectionLength":
break;
default:
pInfo.SetValue(retControl,pInfo.GetValue(subject,null),null);
break;
}
}
catch(Exception ex)
{
Console.WriteLine("Could not assign the value of {0} to \nObject:\t{1}\nOf Type:\t{2}\nBecause:\t{3}", pInfo.Name, subject.Name, ctrlType.Name, ex.Message);//Never happens
}
}
}
foreach(Binding ctrlBinding in subject.DataBindings)
{
try
{
string BindingMember = ctrlBinding.BindingMemberInfo.BindingMember;
string BindingField = BindingMember.Substring(BindingMember.LastIndexOf(".")); retControl.DataBindings.Add(ctrlBinding.PropertyName,
DataSource[i],BindingField);
}
catch(Exception)
{
MessageBox.Show("Exception thrown at line 139");//Never happens
}
}
return retControl;
}



I know this is a large chunk of code. I apologize for that. Thanks for any help you may be able to give. I would like to know any and all reasons why a DataBinding would fail. There has to be a reason for this.

.