How does .NET property databinding work?

C

cjard

I ask, because I have a textbox bound to a bindingsource, which is
bound to a datatable(row)

The datatable is typed, and hence exports a Property called Column1
I added another property to the datatable by editing the partial
class, and Called it ColumnX - it simply returns "Hello World" all the
time

Then I tried to bind my textbox to it, editing the binding for .Text
from xyzBindingSource - Column1
To become: xyzBindingSource - ColumnX

Upon starting the app, I receive the error that "Cannot bind to the
property or column ColumnX on the DataSource."

The autogenerated code to do the binding looks like:
this.normalColTextBox.DataBindings.Add(
new System.Windows.Forms.Binding(
"Enabled", this.dataTable1BindingSource, "ColumnX", true,
OnPropertyChanged, "False"
)
);

What voodoo is going on here, whereby my datatablerow does indeed have
2 properties, Column1 and ColumnX, but only one of them is available
for binding?
 
N

Nicholas Paldino [.NET/C# MVP]

cjard,

When binding to a data set, it uses the implementation of
ICustomTypeDescriptor on the row to determine what properties to bind to,
not reflection on the properties. The reason your property doesn't show up
is that the data row takes its type description from the columns on the
underlying table. So if you want your row to expose that property through
databinding, you have to add the column to the underlying table, and then
expose the value of the property by getting the value from the underlying
row.
 
C

cjard

cjard,

When binding to a data set, it uses the implementation of
ICustomTypeDescriptor on the row to determine what properties to bind to,
not reflection on the properties.
Oh, what a nuisance. Is there any way to access the code that is doing
the examination of the row?
The reason your property doesn't show up
is that the data row takes its type description from the columns on the
underlying table. So if you want your row to expose that property through
databinding, you have to add the column to the underlying table, and then
expose the value of the property by getting the value from the underlying
row.
This creates significant drag for me.. I was hoping to avoid such a
nuisance. Can you think of a better way to do it, rather than adding
dummy columns, that I will never use, just so I can bind some boolean
properties to values that can be easily calculated from the state of
the row? The annoying thing is, that if I have to add dummy columns,
the number of columns present in the dataset will triple.

Alternately, can some more intelligent code be used to form a row's
value? For example, the Expression property can add two columns
together, but I want a more intelligent coding hook.. If there were
some way to make a column call to a property for its value in a way
that wont be destroyed by the design autogenerator, I'd like to hear
it :)


e.g. the designer generates this:

[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public string PKCol {
get {
return ((string)
(this[this.tableDataTable1.PKColColumn]));
}
set {
this[this.tableDataTable1.PKColColumn] = value;
}
}


I'd like to generate the equivalent (indeed I have already done so but
it is not enumerated as per your explanation) by hand and not have the
designer destroy it when it is run.

Could I, for example, create a custom class and set my column to be of
that type.. When called upon for its value, can that class determine
the row it is on, and hence deduce the boolean necessary for binding?
Is this a hugely memory intensive solution to the relatively trivial
problem?


Another, less sophisticated approach I considered was simply of having
a custom class that is essentially a Dictionary<RowState, boolean>
stored in the .Tag of each control on the form and upon the
bindingsource positionchanged event, just enumerating all the cotnrols
on the form and setting their enabled-ness relative to what is gotten
out of the Tag dictionary:

PositionChanged(object sender, EventArgs e){
foreach(Control c in myControlCollection)
c.Enabled = c.Tag[currentRow.RowState];
}

//currentRow is a property that deduces the current row from
BindSource.Current
//myControlCOllection is a manually built collection of controls that
must be changed enabled-ness
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top