Binding controls to custom classes

S

Scott Mueller

I have a question about simple binding:
(please forgive any syntax errors... I am at home, where I do not have
Vb.Net installed, and I rely far too much on Vb's intellisense!)

If I have two textboxes, Textbox1 and Textbox2, and add a databinding to
Textbox2 as such:

Textbox2.Databindings.Add("Text",Textbox1,"Text")

Anything typed into Textbox1 is mirrored in Textbox2.

Now suppose I want to bind the text property of Textbox2 to a property in a
class that I've written:

Class TestClass
Private m_StringValue as String

Public Property StringValue() as String
Get
Return m_StringValue
End Get
Set(Value as String)
m_StringValue = Value
End Set
End Property

Sub New(InitialValue as String)
m_StringValue = InitialValue
End Sub
End Class

Running the following code does not produce the results I would expect:

Sub Main
Dim MyClass as New TestClass("Test")
TextBox2.SetDataBindings("Text",MyClass,"StringValue")
MyClass.StringValue = "New Test"
End Sub

The Text property of Textbox2 at the end of this code fragment is still
"Test", not "New Test"

Do I need to implement any interfaces to cause the changes to the
StringValue property to propogate up to the bound textbox?

Thanks in advance!

Scott Mueller
(e-mail address removed)
 
F

Fergus Cooney

Hi Scott,

Dim oBind As Binding ' (sTargetProperty, oDataSource, sSourceMember)
oBind = New Binding ("Text", oMyClass, "MyClassProperty")
TextBox2.DataBindings.Add (oBind)

I never knew that two TextBoxes could be tied together. So thanks, you've
opened up a new avenue of enquiry. :)

I haven't got very far but the blurb for Class Binding says:
You can specify an instance of any of the following classes for the
data source:
DataSet, DataTable, DataView, DataViewManager
Any class that implements the IList interface. (or IBindingList,
ITypedList)
Any class. [Though contradicted by Binding Class overview]

As usual the examples are over simplistic and don't tell how to roll your
own. :-(

There's a prototype IList below to save you some typing. ;-)

I've got as far as
TextBox2.DataBindings.Add (New Binding ("Text", oSrc, "Foo"))
But I get an ArgumentException. and no information about what argument or
to what.

Over to you. Scott!! Come back with any progress? ;-)

Regards,
Fergus

<code>
Public Class BindableClass : Implements IList
Private alList As New ArrayList
'-----------------------------------------------------------------
Overridable OverLoads ReadOnly _
Public Property IsFixedSize As Boolean _
Implements IList.IsFixedSize
Get
Return True
End Get
End Property
'-----------------------------------------------------------------
Overridable OverLoads ReadOnly _
Public Property IsReadOnly As Boolean _
Implements IList.IsReadOnly
Get
Return True
End Get
End Property
'-----------------------------------------------------------------
Overridable OverLoads ReadOnly _
Public Property Count As Integer _
Implements ICollection.Count
Get
Return 0
End Get
End Property
'-----------------------------------------------------------------
Overridable OverLoads ReadOnly _
Public Property IsSynchronized As Boolean _
Implements ICollection.IsSynchronized
Get
Return True
End Get
End Property
'-----------------------------------------------------------------
Overridable OverLoads Default _
Public Property Item (ByVal Index As Integer) As Object _
Implements IList.Item
Get
Return alList (Index)
End Get
Set
End Set
End Property
'-----------------------------------------------------------------
Overridable OverLoads ReadOnly _
Public Property SyncRoot As Object _
Implements ICollection.SyncRoot
Get
Return Nothing
End Get
End Property
'-----------------------------------------------------------------
Public Overridable OverLoads Function Add (ByVal Value As Object) _
As Integer Implements IList.Add
Return alList.Add (Value)
End Function
'-----------------------------------------------------------------
Overridable OverLoads _
Public Sub Clear Implements IList.Clear
End Sub
'-----------------------------------------------------------------
Overridable OverLoads _
Public Sub CopyTo (aArray As Array, Index As Integer) _
Implements ICollection.CopyTo
End Sub
'-----------------------------------------------------------------
Overridable OverLoads _
Public Function Contains (ByVal Value As Object) As Boolean _
Implements IList.Contains
End Function
'-----------------------------------------------------------------
Overridable OverLoads _
Public Function GetEnumerator As IEnumerator _
Implements ICollection.GetEnumerator
End Function
'-----------------------------------------------------------------
Overridable OverLoads _
Public Function IndexOf (ByVal Value As Object) As Integer _
Implements IList.IndexOf
End Function
'-----------------------------------------------------------------
Overridable OverLoads _
Public Sub Insert (ByVal Index As Integer, ByVal Value As Object) _
Implements IList.Insert
End Sub
'-----------------------------------------------------------------
Overridable OverLoads _
Public Sub Remove (ByVal Value As Object) _
Implements IList.Remove
End Sub
'-----------------------------------------------------------------
Overridable OverLoads _
Public Sub RemoveAt (ByVal Index As Integer) _
Implements IList.RemoveAt
End Sub
End Class
</code>
 
D

Dean Sharp

Everything that I have read or coded regarding data binding (which is more
than I ever wanted to know) tells me that binding is really one way. It's
meant to work from the user interface to the datasource only and not the
other direction. Near as I can tell, this is because the binding manager
knows when the control changes by the validate event, but has no way of
knowing when the custom class changes. I have even tried to do work arounds
by refreshing the bindings or calling a EndCurrentEdit on the Binding
Manager (this used to refresh the data in VB6). Aside from rebinding the
data, I have yet to find a way to update the control when the datasource
changes.
 
F

Fergus Cooney

Hi Dean,

The example that Scott gave of two textboxes tied together - type into one
and the characters appear in both - shows that a Control is capable of being
both source and destination - unless there is some intermediate doing the job.

Perhaps it's too soon to give up hope? :)

I would hope that there are events that the custom class can raise to
say - here's some more data. Lack of decent documentation is a big problem
here.

Regards,
Fergus
 
D

Dean Sharp

Good point. You are correct Fergus. Although I would argue that I am not
totally mistaken. Given the example of the two texboxes, one updates only
after loosing focus (actually the validate event) and the other updates as
you type. It would seem to me that if it truly was meant to be two way,
then they would both behave the same. Of course it is also entirely
possible that it was meant to be two way and it just happens to have bugs.
:)

By the way, to achieve the same behavior on both textboxes, you have to bind
each to the other.

Also, keep in mind that this is a very simple example of binding. Other
examples using different types of objects require a lot more work to get the
same behavior. Controls to custom data classes can be cumbersome. Again, I
would think that it would work without work around code if it was truly two
way.

If anyone finds a simple answer, I would love to rewrite some code. :)
 
S

Scott Mueller

Actually, Dean, the second textbox does change as you type... at least for
me. It appears to me that the a "property changed" notification is sent by
the OnTextChange method of the TextBox. Here's another interesting twist...
Take the following code:

Sub Main
Dim MyClass as New TestClass("Test")
TextBox2.SetDataBindings(New Binding("Text",MyClass.StringValue,""))
MyClass.StringValue = "New Test"
End Sub


Class TestClass
Private m_StringValue as String

Public Property StringValue() as String
Get
Return m_StringValue
End Get
Set(Value as String)
m_StringValue = Value
End Set
End Property

Sub New(InitialValue as String)
m_StringValue = InitialValue
End Sub
End Class

Running this code produces a textbox with the text set to "Test"

Now alter TestClass to look like this:

Class TestClass
Private m_StringValue as String
Public Event StringValueChanged(e As PropertyChangedEventArgs)
Public Property StringValue() as String

Get
Return m_StringValue
End Get
Set(Value as String)
m_StringValue = Value
RaiseEvent StringValueChanged(New PropertyChangedEventArgs("StringValue"))
End Set
End Property

Sub New(InitialValue as String)
m_StringValue = InitialValue
End Sub
End Class


Run the program now, and TextBox2.SetDataBindings(New
Binding("Text",MyClass.StringValue,"")) throws an exception.

Getting warm?
 

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