Data Binding to a object...

  • Thread starter Thread starter Simon Verona
  • Start date Start date
S

Simon Verona

I'm not sure if I'm going down the correct route...

I have a class which exposes a number of properties of an object (in this
case the object represents a customer). Can I then use this object to
databind to text boxes etc?

I can't use a dataset as the object has loads of derived logic, for example
updating one property may actually update several database fields for
example.

Hope I've explained this clear enough...

Regards
Simon
 
As long as your object implements IList, ICollection, IEnumerable then you
should be OK
 
OHM

I don't suppose you've got any references to actual code examples /
walkthroughs? I'm searching through google, but as usual... it's not the
answer that matters, it's the correct question - which is obviously alluding
me!

Many thanks for your help.

Simon
 
Hi,

Don’t forget Implements IEditableObject if you want to be able to
change the bound data.

Ken
---------------------
 
Simon,
As OHM suggested, you need to implement IList, ICollection, IEnumerable if
you want to "edit" a list of items. If you have a single item, you do not
need to implement those interfaces.

In my experience IEditableObject is useful but not required to change bound
data, if you fully implement IEditableObject you can cancel the change,
without IEditableObject the change is made, period.

This article appears to be a good starting point on data binding.
http://support.microsoft.com/default.aspx?scid=kb;en-us;313482


Here is a simple sample of binding to an Object:

Public Class Person

Private m_text1 As String
Private m_text2 As String

Public Sub New()
m_text1 = String.Empty
m_text2 = String.Empty
End Sub

Public Property Text1() As String
Get
Return m_text1
End Get
Set(ByVal value As String)
m_text1 = value
End Set
End Property

Public Property Text2() As String
Get
Return m_text2
End Get
Set(ByVal value As String)
m_text2 = value
End Set
End Property

End Class


Public Class PersonForm
Inherits System.Windows.Forms.Form

' ... designer generated code

Private aPerson As New Person

Private Sub SamSpadeForm_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.TextBox1.DataBindings.Add("Text", aPerson, "Text1")
Me.TextBox2.DataBindings.Add("Text", aPerson, "Text2")
End Sub

End Class

Hope this helps
Jay
 
The only problem with this is that if you change the aPerson.Text1 value
this is not reflected in the TextBox1

--

OHM ( Terry Burns )
. . . One-Handed-Man . . .
 
Terry,
The only problem with this is that if you change the aPerson.Text1 value
this is not reflected in the TextBox1
That's because I left out the notification. :-( Here is a version with
Notifications. :-)

Public Class Person

Public Event Text1Changed As EventHandler
Public Event Text2Changed As EventHandler

Private m_text1 As String
Private m_text2 As String

Public Sub New()
m_text1 = String.Empty
m_text2 = String.Empty
End Sub

Public Property Text1() As String
Get
Return m_text1
End Get
Set(ByVal value As String)
m_text1 = value
OnText1Changed(EventArgs.Empty)
End Set
End Property

Public Property Text2() As String
Get
Return m_text2
End Get
Set(ByVal value As String)
m_text2 = value
OnText2Changed(EventArgs.Empty)
End Set
End Property

Protected Overridable Sub OnText1Changed(ByVal e As EventArgs)
RaiseEvent Text1Changed(Me, e)
End Sub

Protected Overridable Sub OnText2Changed(ByVal e As EventArgs)
RaiseEvent Text2Changed(Me, e)
End Sub

End Class

I tested the above in VS.NET 2003, Changing aPerson.Test1 in the above
changes it in TextBox1!

I don't have a clear link that explains the above, if you want it or need it
I can look for it later.

Hope this helps
Jay
 
So do I read it that I don't need to implement all the interfaces if I just
have a single record ????

Simon
 
Simon,
As I stated earlier: Correct! you don't need to implement any interfaces if
you have a single object ("record").

You need to include a Text1Changed event for the Text1 property, if you can
change the object outside of the form, if only the form can change the
object/property, then the event is not as important.

The "Changed" event needs to be named the same as the property, with Changed
as the suffix, as my Person example shows.

Hope this helps
Jay
 
Thanks, I'll take a read and see what I can learn here !

--

OHM ( Terry Burns )
. . . One-Handed-Man . . .
 
Thanks Jay...

I've got it working using the data binding in code...

I'd like to be able to do the data-binding in the designer.... I guess I
need another interface?

Regards
Simon
 
Simon,
As far as I can tell the designer data-binding requires binding to a list of
items.

I am not aware of any interface that will enable you to bind in the designer
to a single object. Other then Making your single object appear to be a
list, which IMHO is more work then simply adding the data binding
manually...

Considering there is more work on defining the object to support data
binding, then the databinding itself, I personally don't have a problem with
this.

Hope this helps
Jay
 
If the OP is building an inherited control then custom properties can be
bound to the properties window with an attribute tag. Maybe that would
help.?



--

OHM ( Terry Burns )
. . . One-Handed-Man . . .

Time flies when you don't know what you're doing
 
Could I perhaps then inherit the textbox and add fields for the "object
name" and property to map to and then get the object using reflection to do
the mapping in code from within the inherited control?? Or am I being too
ambitious????


Thanks for all your help so far.

Simon
 
If you want to set a wrapped control's custom property from the designer you
need to add attribute tags. When its added to the form you will see the
custom property, is this what you need ?

IE
<Browsable(True), Category("Appearance")> _

Public Property xxxxx as xxxxxxxx

..

..

..


--

OHM ( Terry Burns )
. . . One-Handed-Man . . .

Time flies when you don't know what you're doing

Simon Verona said:
Could I perhaps then inherit the textbox and add fields for the "object
name" and property to map to and then get the object using reflection to do
the mapping in code from within the inherited control?? Or am I being too
ambitious????


Thanks for all your help so far.

Simon
"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote in message
If the OP is building an inherited control then custom properties can be
bound to the properties window with an attribute tag. Maybe that would
help.?



--

OHM ( Terry Burns )
. . . One-Handed-Man . . .

Time flies when you don't know what you're doing

list problem
with if
you
interfaces
if
I
just
have a single record ????

Simon
message
Terry,
The only problem with this is that if you change the aPerson.Text1
value
this is not reflected in the TextBox1
That's because I left out the notification. :-( Here is a version
with
Notifications. :-)

Public Class Person

Public Event Text1Changed As EventHandler
Public Event Text2Changed As EventHandler

Private m_text1 As String
Private m_text2 As String

Public Sub New()
m_text1 = String.Empty
m_text2 = String.Empty
End Sub

Public Property Text1() As String
Get
Return m_text1
End Get
Set(ByVal value As String)
m_text1 = value
OnText1Changed(EventArgs.Empty)
End Set
End Property

Public Property Text2() As String
Get
Return m_text2
End Get
Set(ByVal value As String)
m_text2 = value
OnText2Changed(EventArgs.Empty)
End Set
End Property

Protected Overridable Sub OnText1Changed(ByVal e As EventArgs)
RaiseEvent Text1Changed(Me, e)
End Sub

Protected Overridable Sub OnText2Changed(ByVal e As EventArgs)
RaiseEvent Text2Changed(Me, e)
End Sub

End Class

I tested the above in VS.NET 2003, Changing aPerson.Test1 in the
above
changes it in TextBox1!

I don't have a clear link that explains the above, if you want
it
or
need
it
I can look for it later.

Hope this helps
Jay

"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com>
wrote
in
message
The only problem with this is that if you change the aPerson.Text1
value
this is not reflected in the TextBox1

--

OHM ( Terry Burns )
. . . One-Handed-Man . . .


"Jay B. Harlow [MVP - Outlook]" <[email protected]>
wrote
in
message
Simon,
As OHM suggested, you need to implement IList, ICollection,
IEnumerable
if
you want to "edit" a list of items. If you have a single item,
you
do
not
need to implement those interfaces.

In my experience IEditableObject is useful but not
required
to cancel
the
 
Simon,
You do not need an inherited control to bind to an object. You just need the
object, Windows Forms supplies the rest!

I don't see where reflection would help per se, it sounds like you want to
throw a lot of code at a problem that is simple enough to solve, with very
little code.

Of course if you want "better" design time support, a custom TextBox that
has a Person/Object property & a PropertyName property may be a good
alternative:

The "problem" with creating a custom TextBox, is you will need to create
custom versions of every other control. A Property Extender may be a better
alternative.

Here is a version of a custom TextBox:

Imports System.ComponentModel

Public Class BindableTextBox
Inherits TextBox

Private m_propertyName As String
Private m_dataSource As Object
Private m_dataMember As String

Public Sub New()
m_propertyName = String.Empty
m_dataSource = Nothing
m_dataMember = String.Empty
End Sub

<Category("Data"), DefaultValue("")> _
Public Property PropertyName() As String
Get
Return m_propertyName
End Get
Set(ByVal value As String)
m_propertyName = value
DataBind()
End Set
End Property

<Category("Data")> _
Public Property DataSource() As Object
Get
Return m_dataSource
End Get
Set(ByVal value As Object)
m_dataSource = value
DataBind()
End Set
End Property

<Category("Data"), DefaultValue("")> _
Public Property DataMember() As String
Get
Return m_dataMember
End Get
Set(ByVal value As String)
m_dataMember = value
DataBind()
End Set
End Property

Public Sub DataBind()
If m_propertyName Is Nothing Then Exit Sub
If m_dataSource Is Nothing Then Exit Sub
If m_dataMember Is Nothing Then Exit Sub
Me.DataBindings.Add(m_propertyName, m_dataSource, m_dataMember)
End Sub

End Class

On your form you can use BindableTextBox, use the designer to set the
DataMember & PropertyName properties, then within your code set the
DataSource property to an instance of your object.

For details on making the above class better behaved in the designer, check
out the following articles.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/usingpropgrid.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/vsnetpropbrow.asp


I would simply do all the Control.DataBindings.Add in the Set routine for
the object property on my form, then when I create the form I would set this
Object Property

Public Class PersonForm
Inherits System.Windows.Forms.Form

' designer generated code

Private m_person As Person

Public Property Person As Person
Get
Return m_person
End Get
Set(ByVal value As Person)
m_person = value
If value Is Nothing Then Exit Property
Me.TextBox1.DataBindings.Add("Text", aPerson, "Text1")
Me.TextBox2.DataBindings.Add("Text", aPerson, "Text2")
End Set
End Property

End Form

You should also include code in Person Set to un bind the previous person
object.

Hope this helps
Jay

Simon Verona said:
Could I perhaps then inherit the textbox and add fields for the "object
name" and property to map to and then get the object using reflection to do
the mapping in code from within the inherited control?? Or am I being too
ambitious????


Thanks for all your help so far.

Simon
"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote in message
<<snip>>
 
I'm not 100% sure how this would help me..

If I exposed all my properties of my class using this method, how would this
help me to bind a text box for example to a property of a specific instance
of this class in the designer???

Or have I totally misunderstood you ??

Thanks in advance!

Simon
 
Jay

Thats the sort of code I had in mind to add to an "inherited" text box....
As you say I will still need code in the form to set the datasource to the
instance of my object. I was hoping that I could write some code within my
inherited control so that it took the object name as the "datasource" and
internally mapped to the object itself...

The reason I want to do this is that I have a number of data entry forms to
write that are bound to custom classes and it would be much more simple if I
could write it so that I can do it all in the form designer without having
to remember to go back and add code to do the binding...

I'm just trying to make my life more simple by doing the "hard" work once!

Thanks in advance.
Simon
 
Back
Top