Late binding of forms???

P

Peter Van Wilrijk

Hi,

In VB6 I have the following code ...

Dim frmLink As Form
Set frmLink = Forms.Add(stringformname)
frmLink.Show
'wait until all data has been loaded
Do Until frmLink.Loaded = 21
DoEvent
Loop
frmLink.Loaded = 31
Call frmLink.ExecuteLinked(strparameter)

stingformname and strparameter are passed as parameters to the function.
I understand this code might cause trouble : 1) when the form with
name stringformname doesn't exist or 2) if this form exists, but doesn't
contain a public method ExecuteLinked. I can catch it with
errorhandling of course.

I want to convert this code to VB.NET, but I get errors at DESIGN TIME,
because VB.NET doesn't know which form will be used and so doesn't
recognize the methode ExecuteLinked as a public function of frmLink.

I've read some things about this issue but I do not manage to find a
workaround. Any idea really appreciated.

Thanks,
Regards,
Peter Van wilrijk.
 
C

Carlos J. Quintero [VB MVP]

Hi Peter,

You can declare the form variable with the specific form type and cast to
it:

Dim frmLink As MyFormWithCustomMethods
Set frmLink = DirectCast(Forms.Add(stringformname),
MyFormWithCustomMethods)
frmLink.Show
'wait until all data has been loaded
Do Until frmLink.Loaded = 21
DoEvent
Loop
frmLink.Loaded = 31
Call frmLink.ExecuteLinked(strparameter)


--

Best regards,

Carlos J. Quintero

MZ-Tools: Productivity add-ins for Visual Studio .NET, VB6, VB5 and VBA
You can code, design and document much faster.
Free resources for add-in developers:
http://www.mztools.com
 
P

Peter Van Wilrijk

Hi Carlos,

Sorry, I'm rather new in .NET. May I conclude from your example that
MyFormWithCustomMethods is a kind of template form in which you
implement the public method without code, only used to make the method
available to inheriting forms??

I've tested you're suggestion with this code in Form1 and a empty public
method ExecuteLinked in both Form2 and Form3, but I get a (design time
error) line under forms in the DirectCast instruction, as if the system
doesn't recognize the forms collection. I work with framework 1.0,
perhaps I've to upgrade?

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim frmLink As Form2
Dim strFormName As String
strFormName = "Form3"
frmLink = DirectCast(forms.add(strFormName), Form2)
frmLink.Show()
Call frmLink.ExecuteLinked()
End Sub


Thanks a lot.
Peter.
 
J

Jeff Jarrell

Peter,
define an interface, then have each form implement the interface.
then cast cast form to the interface type and use the interface methods.

jeff
 
C

Carlos J. Quintero [VB MVP]

Hi Peter,

Ah, yes, there is no Forms collection in .NET, so if you need one you must
create it. If you only want the Add method to create forms by name (string),
you can do it with an Activator.CreateInstance call. See this thread:

http://groups.google.es/group/micro...tion+VB.NET+VB6&rnum=4&hl=es#28cb60565e1cd9d4

--

Best regards,

Carlos J. Quintero

MZ-Tools: Productivity add-ins for Visual Studio .NET, VB6, VB5 and VBA
You can code, design and document much faster.
Free resources for add-in developers:
http://www.mztools.com
 
P

Peter Van Wilrijk

Hi Carlos, Jeff,

Thanks a lot for your suggestions. I'm really happy with this. Now I
can call the form.

Jeff, what do you mean with cast form to the interface type and use the
interface methods?

I just tried to implement an interface for the first time in my life.
Everything seems all right. I've the following interface and I have
added the code and "implements" keywords in forms2 and froms3

Only problem unsolved is the the editor underlines the instruction call
myForm.executelinked() with the message
"C:\VBNET\DBTESTER\WindowsApplication2\Form1.vb(71): 'executelinked' is
not a member of 'System.Windows.Forms.Form'."

Any idea here?? Should I move the interface to a module instead of
under the form definition?

---
Dim myForm As Form
Dim MyFormName As String = "WindowsApplication2.Form2"
Dim ConstructorParameterArray As Object() = New Object() {}
myForm = System.Activator.CreateInstance(Type.GetType(MyFormName, True,
True), ConstructorParameterArray)
myForm.Show()
 
P

Peter Van Wilrijk

Hi Carlos and Jeff,

Now the solution I was looking for is complete. Thanks a lot. I post
it for others who might want to do same. I didn't manage to execute the
public procedure in Form2 and Form3 via "Interfaces" and "Implements"
but I found an alternative using InvokeMember. I don't know it's the
best way to do it, but EUREKA, it works!!

I guess my attempt to test "interface" and "implements" failed because
ExecuteLinked is known in Form2 and Form3 ... but not in the object
myForm ... or might it be possible to attach implements to the
declaration ... Dim myForm as Form?

wonder the interface option caused problems

-- FORM1 with only 2 buttons

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
CallFormLink("Form2")
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
CallFormLink("Form3")
End Sub

Private Sub CallFormLink(ByVal strFormName As String)
Dim myForm As Form
Dim ConstructorParameterArray As Object() = New Object() {}
'It seems necessary to specify the name of the application
strFormName = Application.ProductName.ToString & "." & strFormName
myForm =
System.Activator.CreateInstance(Type.GetType(strFormName, True, True),
ConstructorParameterArray)
myForm.Show()
myForm.GetType().InvokeMember("ExecuteLinked",
Reflection.BindingFlags.InvokeMethod, Nothing, myForm, Nothing)
End Sub

-- FROM2

Sub ExecuteLinked()
MsgBox("form2")
End Sub


-- FORM3

Sub ExecuteLinked()
MsgBox("form3")
End Sub

Kind Regards,
Peter Van Wilrijk.
 
J

Jeff Jarrell

Peter,

Using an interface... you are sooo close. It is a VERY important lesson to
learn to use the interfaces and I am not saying it is the solution to your
problem. But for educational purposes here goes.

Where you dim it "myForm as Form", it should be dimmed as the Interface
type. Something like the following...
'
dim myForm as IMYINTERFACE

myForm = new FORM1 ' note that you can do this since you "implemented" the
interface in form1, form2,form3
or
myForm = new FORM2 ' note that you can do this since you "implemented" the
interface in form1, form2,form3
or
myForm = new FORM3 ' note that you can do this since you "implemented" the
interface in form1, form2,form3
or
dim aForm as new form
myForm = ctype(aForm,IMYINTERFACE)

'now execute
myForm.executeLink

Now when you look at the methods and properties on myForm using the
intellisense, you will only see the methods and properties that you have
exposed via the interface. Not all other stuff that you know is there
because you know they are forms. This is one way to make polymorphism work.
An interface doesn't even have to have a lot of methods and properties. An
interface doesn't even have to have a lot of methods and properties.

Now when in your sample you using reflection to accomplish a number of
things. Not all of which I expect is relevant to your real problem. When I
use reflection in application code it is typically to break the rules of oop
in some way. Since myForm is dim as form, the executeLink isn't available
through the form type. But reflection lets you do it any way since the
object is "really" a form1, form2, or form3.

hope this helps.
jeff
 
P

Peter Van Wilrijk

Hi,

It sure does help Jeff, thanks a lot ... but you made me more curious
and so I continued testing ... raising new questions :).

I add once more the code at the end in order to make it clear ...

1) I added my interface again. The page
http://msdn.microsoft.com/library/d.../en-us/vbcn7/html/vaconcreatinginterfaces.asp
(step 6) tells me to put it in a module block. I had to move it behind
END MODULE to make it work. Are there any rules about where to place
the interface definition?

2) I implemented the interface in Form2 and Form3 and added method
CallFormLink2 in Form1

Great, it works as you promised. So, I learned interfaces forcing to
implement some code and offering design time intellisense support. Are
there any other reasons to use interfaces? I still think in VB6-ways
I'm afraid :)

Now, since I wanted to call forms based on there (string) name as done
in CallFormLink, avoiding declarations "as New Form2", "as New Form3"
....
enabling a system where formnames are gathered in a databasetable, a
system where application execution can easily be manipulated via the
database instead of by changing code
....
I wondered I could combine you're interface strategy with the Activator
strategy to call forms "dynamically".

So I introduced CallFormLink3, but here I get a Design time error (*1)
on the line myForm.Show, since the system doesn't early bind myForm with
a form and the interface only supports the method ExecuteLinker.

Than I made a new attempt in CallFormLink4, but with the same result.
So to make it work I need a uninstanciated form object (Dim myForm As
Form ... as in CallFormLink) expanded with the implementation of
IMyInterface. I wonder this can be done, because at this point I also
found out I lost the myForm.Show functionality in CallFormLink2.

I ran the program again and saw "executelinker" being executed in form2
and form3 (the messageboxes appear) but the forms are not shown and I
get a compile time error when adding myForm.Show on the line above
myForm.ExecuteLinker in method CallFormLink2.

So it seems I downgraded the functionality of my forms to only the
method ExecuteLinker by declaring it with type IMyInterface, while I
want to keep the functionality offered by the form class. Any idea?

--

HERE FOLLOWS THE CODE

-- added in module1.vb

Public Interface IMyInterface
Sub ExecuteLinker()
End Interface

-- form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
'CallFormLink("Form2")
'CallFormLink2("Form2")
CallFormLink3("Form2")
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
'CallFormLink("Form3")
'CallFormLink2("Form3")
CallFormLink3("Form3")
End Sub

Private Sub CallFormLink(ByVal strFormName As String)
Dim myForm As Form
Dim ConstructorParameterArray As Object() = New Object() {}
'It seems necessary to specify the name of the application
strFormName = Application.ProductName.ToString & "." & strFormName
myForm =
System.Activator.CreateInstance(Type.GetType(strFormName, True, True),
ConstructorParameterArray)
myForm.Show()
myForm.GetType().InvokeMember("ExecuteLinked",
Reflection.BindingFlags.InvokeMethod, Nothing, myForm, Nothing)
End Sub

Private Sub CallFormLink2(ByVal strFormName As String)
Dim myForm As IMyInterface
Select Case strFormName
Case "Form2"
myForm = New Form2()
Case "Form3"
myForm = New Form3()
End Select
myForm.ExecuteLinker()
End Sub

Private Sub CallFormLink3(ByVal strFormName As String)
Dim myForm As IMyInterface
Dim ConstructorParameterArray As Object() = New Object() {}
'It seems necessary to specify the name of the application
strFormName = Application.ProductName.ToString & "." & strFormName
myForm =
System.Activator.CreateInstance(Type.GetType(strFormName, True, True),
ConstructorParameterArray)
*1 myForm.Show()
myForm.ExecuteLinker()
End Sub

Private Sub CallFormLink4(ByVal strFormName As String)
Dim myForm As IMyInterface
Dim aForm As New Form()
myForm = CType(aForm, IMyInterface)
Dim ConstructorParameterArray As Object() = New Object() {}
'It seems necessary to specify the name of the application
strFormName = Application.ProductName.ToString & "." & strFormName
myForm =
System.Activator.CreateInstance(Type.GetType(strFormName, True, True),
ConstructorParameterArray)
*1 myForm.show()
myForm.ExecuteLinker()
End Sub

-- form2

Implements IMyInterface

Sub ExecuteLinked()
MsgBox("form2")
End Sub

Sub executelinker() Implements IMyInterface.ExecuteLinker
MsgBox("form2 Imp")
End Sub

-- form3

Implements IMyInterface

Sub ExecuteLinked()
MsgBox("form3")
End Sub

Sub executelinker() Implements IMyInterface.ExecuteLinker
MsgBox("form3 Imp")
End Sub

Thanks,
Kind Regards,
Peter Van Wilrijk.
 
J

Jeff Jarrell

Peter,
1) I try and stick to a convention of one class to a file. That msft article
is a little confusing. Generally, it is a simple file that contains
something like this...

Namespace exact.wx.core
Public Interface ISomething
Sub Execute
End Interface
End Namespace

The namespace is optional, but i find it easier to keep it explicit and in
plain sight.

2) If you are instantiating objects dynamically (forms) that are unknown at
runtime, then the system.activator is the natural way to go. How you manage
the what gets activated is up to you, be it from the database or some other
source. Commonly, this type of feature is implemented via a "factory
pattern".

3) As far as getting your show to execute, I can think of a couple of
things. One way is to dim a form, then cast the myIForm into back to form
as in...
dim f as form
f = ctype(myIFORM,form)
f.show

If you want to be a little spiffier. You can add the show to your interface,
then add a method on the form to map from the interface into the form.show.
Note you shouldn't name method show (in the form class), but see the
implements on the end.

Public Interface ISomething
Sub Execute
Sub Close
Sub Refresh
Sub Show
End Interface

Public Sub Close1() Implements ISomething.Close
Me.Close()
End Sub

Public Sub Refresh1() Implements ISomething.Refresh
Me.Refresh()
End Sub

Public Sub Show1() Implements ISometing.Show
Me.Show()
End Sub

Ultimately this is about polymorphism which you can make happen via
inheritance or interface (as we have been discussing). Inheritance is used
when descendent objects "is a" relationship of the parent. If objects are
less a like and don't practically share a common implemenation at some level
then it should be an interface.

If each of your dynamic forms really don't relate to one an other in terms
of actual implementation then the interface is the way to go in combination
with the dynamic activation. I'd add more function to the interface to give
you the required external interface you need.

Interfaces are vitally important. The VB.Net changes the whole vb6 way,
although you could do interfaces in VB6. Pick up the book "Head First
Design Patterns". While not .NET it is a good read on objected oriented
principles.

jeff
 
P

Peter Van Wilrijk

Thanks Jeff,

At the moment I still have mixed feeling about OO.

I see and understand some of the advantages, but I get the impression it
might add complexity while it's not needed. I might get more work when
working on often poorly documented code of other programmers and I don't
see why my collegues should bother making seperate classes (eg bycicles
and cars) from a base class (eg vehicles) when I decided to store both
types in the same databasetable.

I'm quite sure I'll once see all advantages clear. Perhaps after I've
read the book, you suggest. I see on the web it's visual attractive. I
hope to find a dutch translation in order to miss nothing. After 10
years of programming in different languages, I really wonder why most
taskmasters aren't prepared to invest more in analysis, design and
documentation, thinking it's an unnecessary extra cost.

About your examples. The expanded interface (show, close, ...) works
fine. I don't manage to let work the other example casting the
interface with the form, since the method from the interface doesn't
become accessible (*1).

Private Sub CallFormLink4(ByVal strFormName As String)
Dim f As Form
Dim intf As IMyInterface
f = CType(intf, Form)
f.Show()
f.executelinker() (*1)
End Sub

This made me wonder I could expand the functionality of the class "Form"
by combining inheritance and interfaces but my .NET environment doesn't
seem to like the following construction :)

Public Class clsForm : Inherits Form
Implements IMyInterface
End Class

Kind regards,
Peter.
 
C

Cor Ligthert [MVP]

Peter,
At the moment I still have mixed feeling about OO.
I assume you mean OOP because OO is a very wide in my opinion not so well
delimited area.

Use it as you need it. If you are working at a program about trafic rules,
than you can create a class for verhicles with all types of verhicles
deriving from that. It makes it easier to describe problems and even you can
create special rules for every type of trafic.

However, in my opinion, don't make OOP the goal of your program. Than you
see those bad programs you are refering to.

Be as well aware that in an organisation with a lot of devellopers there has
to be other rules than in those with few. It has no sense to make a program
in a style based on 200 completely different developpers if that never will
be the situation.

One of the main goals of OOP is reusability and easier describing of the
problem. It is not as I sometimes get the idea that people think, to *use*
multi inheritance, interfaces, polyphorism etc etc.

If your program misses those main goals than it is without sense.

Just my idea.

Cor
 
P

Peter Van Wilrijk

Cor said:
Peter,



I assume you mean OOP because OO is a very wide in my opinion not so well
delimited area.

Use it as you need it. If you are working at a program about trafic rules,
than you can create a class for verhicles with all types of verhicles
deriving from that. It makes it easier to describe problems and even you can
create special rules for every type of trafic.

However, in my opinion, don't make OOP the goal of your program. Than you
see those bad programs you are refering to.

Be as well aware that in an organisation with a lot of devellopers there has
to be other rules than in those with few. It has no sense to make a program
in a style based on 200 completely different developpers if that never will
be the situation.

One of the main goals of OOP is reusability and easier describing of the
problem. It is not as I sometimes get the idea that people think, to *use*
multi inheritance, interfaces, polyphorism etc etc.

If your program misses those main goals than it is without sense.

Just my idea.

Cor

Thanks Cor,

I see what you mean. Logic, but I never thought of it. Those
enhancements offered by OOP are nice things to learn using (theory and
practice by example), but are only to use when you really need them or
when you think they might be better (in whatever way : performance,
reusability, ...) than the things we know from pre-OOP languages, right?

I also noticed OO Languages might (in some cases) be (following the OOP
rules) more restrictive. In my first post I was looking for something
that was really easy in VB6 but wasn't that easy to work out in .NET.
Now I have a solution that works really fine, nevertheless still
wondering whether there's a way to inherit a method to the form class
(to expand the functionality) as it's delivered.

Kind Regards,
Peter.
 

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