Michael,
Thanks for the time and effort! I'll play with this tonight. Look out for my next post!!!
I must admit that I do find reflection confusing!!! I just don't use it enough... I always end up cutting and pasting examples without really looking at *WHY* they work!
Regards
Simon
Hi Simon,
I haven't got the time to get it to work fully (I think the approach is not right), but I guess you'll have a good "manual" with this code.
I have three classes:
a.. Simon (Testform)
b.. SimonData (DataObject Vehicle & Airplane)
c.. SimonTextBox
Good luck with this and please ..... when you get this right, post the code to this thread, so others can have a good sample !!!!
Thanks,
Michael
------------------------------------------------------------------------------
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
'Friend WithEvents myTextBox1 As Simon.myTextBox
Friend WithEvents MyTextBox1 As SimonTextBox.myTextBox
Friend WithEvents MyTextBox2 As SimonTextBox.myTextBox
Friend WithEvents MyTextBox3 As SimonTextBox.myTextBox
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents MyTextBox4 As SimonTextBox.myTextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.MyTextBox1 = New SimonTextBox.myTextBox
Me.MyTextBox2 = New SimonTextBox.myTextBox
Me.MyTextBox3 = New SimonTextBox.myTextBox
Me.Label1 = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.Label3 = New System.Windows.Forms.Label
Me.Label4 = New System.Windows.Forms.Label
Me.MyTextBox4 = New SimonTextBox.myTextBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(200, 209)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 1
Me.Button1.Text = "Button1"
'
'MyTextBox1
'
Me.MyTextBox1.Location = New System.Drawing.Point(30, 33)
Me.MyTextBox1.Name = "MyTextBox1"
Me.MyTextBox1.ObjectName = "Vehicle"
Me.MyTextBox1.PropertyName = "Text"
Me.MyTextBox1.TabIndex = 2
Me.MyTextBox1.Text = "MyTextBox1"
'
'MyTextBox2
'
Me.MyTextBox2.Location = New System.Drawing.Point(30, 66)
Me.MyTextBox2.Name = "MyTextBox2"
Me.MyTextBox2.ObjectName = ""
Me.MyTextBox2.PropertyName = ""
Me.MyTextBox2.TabIndex = 2
Me.MyTextBox2.Text = "MyTextBox2"
'
'MyTextBox3
'
Me.MyTextBox3.Location = New System.Drawing.Point(30, 99)
Me.MyTextBox3.Name = "MyTextBox3"
Me.MyTextBox3.ObjectName = "Airplane"
Me.MyTextBox3.PropertyName = "Text"
Me.MyTextBox3.TabIndex = 2
Me.MyTextBox3.Text = "MyTextBox3"
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(140, 33)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(140, 23)
Me.Label1.TabIndex = 3
Me.Label1.Text = "Bound to Vehicle"
Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(140, 66)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(140, 23)
Me.Label2.TabIndex = 3
Me.Label2.Text = "Not Bound"
Me.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'Label3
'
Me.Label3.Location = New System.Drawing.Point(140, 99)
Me.Label3.Name = "Label3"
Me.Label3.Size = New System.Drawing.Size(140, 23)
Me.Label3.TabIndex = 3
Me.Label3.Text = "Bound to Airplane"
Me.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'Label4
'
Me.Label4.Location = New System.Drawing.Point(140, 132)
Me.Label4.Name = "Label4"
Me.Label4.Size = New System.Drawing.Size(140, 23)
Me.Label4.TabIndex = 3
Me.Label4.Text = """Bound"" to Illegal Object"
Me.Label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'MyTextBox4
'
Me.MyTextBox4.Location = New System.Drawing.Point(30, 132)
Me.MyTextBox4.Name = "MyTextBox4"
Me.MyTextBox4.ObjectName = "Boat"
Me.MyTextBox4.PropertyName = "Text"
Me.MyTextBox4.TabIndex = 2
Me.MyTextBox4.Text = "MyTextBox4"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.MyTextBox1)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.MyTextBox2)
Me.Controls.Add(Me.MyTextBox3)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.Label3)
Me.Controls.Add(Me.Label4)
Me.Controls.Add(Me.MyTextBox4)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
' Dim Vehicle As New Vehicle
' You need to listen for events: WithEvents
Dim WithEvents Vehicle As SimonData.Vehicle
Dim WithEvents Airplane As SimonData.Airplane
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
InitializeDataObjects()
End Sub
#Region " Instantiation "
Private Sub InitializeDataObjects()
Vehicle = New SimonData.Vehicle
Airplane = New SimonData.Airplane
End Sub
#End Region
'Dim DataValues As String
'Private Sub Vehicle_DataChanging(ByVal sender As Object, ByVal e As System.EventArgs) Handles Vehicle.DataChanging
' DataValues = "Old value: " & Vehicle.Data.ToString
'End Sub
'Private Sub Vehicle_DataChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Vehicle.DataChanged
' DataValues += vbCrLf & "New value: " & Vehicle.Data.ToString
' MsgBox(DataValues)
'End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim s As String
s += "Vehicle = " & Me.Vehicle.Data.ToString + vbCrLf
s += "Airplane = " & Me.Airplane.Data.ToString
MsgBox(s)
End Sub
End Class
------------------------------------------------------------------------------
Option Strict Off
Public Class Vehicle
'Implements System.ComponentModel.IBindingList
Private dat As String = "Hello Vehicle"
'Event DataChanged As EventHandler SCOPE YOUR EVENT
Public Event DataChanged As EventHandler
Public Event DataChanging As EventHandler
Public Property Data()
Get
Return dat
End Get
Set(ByVal Value)
Debug.WriteLine("Data Set for Vehicle") : Beep()
If dat = Value Then
' Nothing has changed, so skip all the processing!
Exit Property
End If
OnDataChanging(Me, New EventArgs)
dat = Value
' RaiseEvent DataChanged(Me, New EventArgs)
' THIS IS NOT DONE: DON'T RAISE AN EVENT DIRECTLY
' USE A "On" + EVENT SUB (Convention)
OnDataChanged(Me, New EventArgs)
End Set
End Property
Public Overridable Sub OnDataChanging(ByVal sender As Object, ByVal e As System.EventArgs)
RaiseEvent DataChanging(Me, New EventArgs)
End Sub
Public Overridable Sub OnDataChanged(ByVal sender As Object, ByVal e As System.EventArgs)
RaiseEvent DataChanged(Me, New EventArgs)
End Sub
End Class
*****************************************************************
Option Strict Off
Public Class Airplane
Private dat As String = "Hello Airplane"
'Event DataChanged As EventHandler SCOPE YOUR EVENT
Public Event DataChanged As EventHandler
Public Event DataChanging As EventHandler
Public Property Data()
Get
Return dat
End Get
Set(ByVal Value)
Debug.WriteLine("Data Set for Vehicle") : Beep()
If dat = Value Then
' Nothing has changed, so skip all the processing!
Exit Property
End If
OnDataChanging(Me, New EventArgs)
dat = Value
' RaiseEvent DataChanged(Me, New EventArgs)
' THIS IS NOT DONE: DON'T RAISE AN EVENT DIRECTLY
' USE A "On" + EVENT SUB (Convention)
OnDataChanged(Me, New EventArgs)
End Set
End Property
Public Overridable Sub OnDataChanging(ByVal sender As Object, ByVal e As System.EventArgs)
RaiseEvent DataChanging(Me, New EventArgs)
End Sub
Public Overridable Sub OnDataChanged(ByVal sender As Object, ByVal e As System.EventArgs)
RaiseEvent DataChanged(Me, New EventArgs)
End Sub
End Class
------------------------------------------------------------------------------
Option Strict Off
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Reflection
Public Class myTextBox
Inherits System.Windows.Forms.TextBox
Dim m_ObjectName As String
<EditorBrowsable(EditorBrowsableState.Always), _
Browsable(True), _
Category("Notify"), _
Description("Name of the Object to bind to.")> _
Public Property ObjectName() As String
Get
Return m_ObjectName
End Get
Set(ByVal Value As String)
m_ObjectName = Value
BindData()
End Set
End Property
Dim m_PropertyName As String = "Text"
<EditorBrowsable(EditorBrowsableState.Always), _
Browsable(True), _
Category("Notify"), _
Description("Name of the Property to bind to.")> _
Public Property PropertyName() As String
Get
Return m_PropertyName
End Get
Set(ByVal Value As String)
m_PropertyName = Value
BindData()
End Set
End Property
Private Sub BindData()
Dim o As Object = Me.GetContainerControl
If IsNothing(o) Then Exit Sub
' Sentinel: Only do this at runtime
If Me.DesignMode Then Exit Sub
' Sentinel: Check if we can bind
If IsNothing(m_ObjectName) Or IsNothing(m_PropertyName) Then Exit Sub
' Get a reference to the DataObject
' We can not use "Me.TopLevelControl.GetType()" because that would return the MDI
' in a MDI-Application
' So search for the containing form:
Dim frm As System.Windows.Forms.Control = Me.Parent
Do While Not frm.GetType.BaseType.Equals(GetType(System.Windows.Forms.Form))
frm = frm.Parent
Debug.WriteLine(frm.GetType.BaseType)
Debug.WriteLine(GetType(System.Windows.Forms.Form).ToString)
Loop
Dim myDataObject As Object
Dim t As Type = frm.GetType
Dim fi As FieldInfo()
Dim f As FieldInfo
fi = t.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.Public)
For Each f In fi
If f.FieldType.ToString = "SimonData." & m_ObjectName Then
' we've found the right DataObject (If there's only One per form (of that type))
Debug.WriteLine(CType(f.Name, String) + ": " + f.ToString)
' This is a NEW instance, so basically this is wrong
' but I think you have an idea now where to dig.
myDataObject = Activator.CreateInstance(f.FieldType(), True)
End If
Next
' Sentinel: The Object-Retieval failed
If IsNothing(myDataObject) Then Exit Sub
' Set the Binding
Dim myBinding As New System.Windows.Forms.Binding(m_PropertyName, myDataObject, "Data")
' Clear previous bindings (just in case)
Me.DataBindings.Clear() ' This is a bit drastic, you should only remove the one with the right Property
' Add the Binding
Me.DataBindings.Add(myBinding)
''''''''''''
''' TEST '''
''''''''''''
Dim s As String
s += "Binding set for: " & Me.Name.ToString + vbCrLf
s += "Property: " & m_PropertyName.ToString + vbCrLf
s += "DataSource: " & myDataObject.GetType.Name.ToString + vbCrLf
s += "Path: Data"
MsgBox(s)
''''''''''''
''' TEST '''
''''''''''''
End Sub
Private Sub myTextBox_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.ParentChanged
BindData()
End Sub
End Class