|
-
May 16th, 2008, 08:37 AM
#1
[RESOLVED] [2005] Showing Forms Dynamically
I have a listbox that contains a bunch of form names (all forms exist within my project)
When I user clicks on a form name, I need to load it. This is a rewrite of one of my VB6 projects. In Vb6, I did
Code:
Private Sub List1_Click()
Dim fForm As Form
Set fForm = Forms.Add(List1.List(List1.ListIndex))
fForm.Show
End Sub
Which worked just fine, however, in .NET, as I'm sure you know, the keyword Forms doesn't exist. Moreover Windows.Forms does not have an Add method, so I don't know how to translate this properly.
How would I do that?
-
May 16th, 2008, 08:48 AM
#2
Re: [2005] Showing Forms Dynamically
At the moment I cant think of anything better than this:
VB.NET Code:
Dim formName As String = "Form1"
Dim assm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim frm As Form = TryCast(assm.CreateInstance(String.Format("{0}.{1}", assm.GetName.Name, formName)), Form)
If Not frm Is Nothing Then
frm.Show()
End If
-
May 16th, 2008, 09:00 AM
#3
Re: [2005] Showing Forms Dynamically
I'm sure Atheist's code is much better, but I don't even know what it's doing.
Here's the simpleton way I've done it in the past (this, of course, could become painful with many forms):
vb.net Code:
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Select Case Me.ListBox1.SelectedItem.ToString()
Case "Form2"
Dim f2 As New Form2()
f2.Show()
Case "Form3"
Dim f3 As New Form3()
f3.Show()
End Select
End Sub
-
May 16th, 2008, 09:09 AM
#4
Re: [2005] Showing Forms Dynamically
I'm afraid you need to use a dependency injector to search your app assembly for classes that implement a specific Interface (The same as System.Windows.Form uses would be nice)
And the have the correct ClassName (a String)
and create an object of this typeoff interface
To do so quickly you need to Find a dependency injector written in c# or VB.Net
Good luck.
BTW Atheist is pretty close with his solution
 why can't programmers keep and 31 Oct and 25 dec apart. Why Rating is Useful
for every question you ask provide an answer on another thread.
-
May 16th, 2008, 09:20 AM
#5
Re: [2005] Showing Forms Dynamically
You can use the Activator.CreateInstance to do it:
Code:
Dim t As Type = Type.GetType("Namespace.FormName")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
(VB/C#) is clearly superior to (C#/VB) because it (has/doesn't have) <insert trivial difference here>.
-
May 16th, 2008, 09:32 AM
#6
Re: [2005] Showing Forms Dynamically
As a test I created a new project with two forms (Form1 Form2), and tried this
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As Type = Type.GetType("Namespace.FormName")
Dim frm As Form = CType(Activator.CreateInstance(t), Form2)
frm.Show()
End Sub
With Option Strick On (which I always have), I got no errors, but when I ran it an clicked the button, I got
 Originally Posted by Exception Error
Value cannot be null - points to Form2
Parameter name: type
Troubleshooting tips:
Use the "new" keyword to create an object instance
Check to determine if the object is null before calling the method
Get general help for this exception (I just LOVE this one!  )
I tried New is a variety of different places and in each I was immediately told that it wasn't valid the context in which I was using it.
-
May 16th, 2008, 09:34 AM
#7
Re: [2005] Showing Forms Dynamically
The string passed into Type.GetType must be in the format:
AssemblyName.ClassName
So change "Namespace" to whatever your assemblyname is.
-
May 16th, 2008, 09:55 AM
#8
Re: [2005] Showing Forms Dynamically
Yes, by Namespace, I meant AssemblyName.
So if your project is called Project1 and your listbox contains Form1, Form2 and Form3 and you click on Form2, your code would have to be:
Code:
Dim t As Type = Type.GetType("Project1.Form2")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
Note that the second parameter for the CType is Form and not Form2. Having Form2 in there is what may be throwing your exception.
(VB/C#) is clearly superior to (C#/VB) because it (has/doesn't have) <insert trivial difference here>.
-
May 16th, 2008, 10:16 AM
#9
Lively Member
Re: [2005] Showing Forms Dynamically
Hi!
In former Times I did a little other approach:
I filled al List(Of Type) or an array in a way like this:
Code:
dim Src=new Type() { Gettype(Form1),Gettype(Form2),Gettype(Form3) }
Then I told my Listbox:
Code:
Listbox1.DisplayMember="Name"
Listbox1.DataSource=Src
On Listbox1_SelectionChanged() I used the Activator to create Instances of the selected Type in the Listbox1.
-
May 16th, 2008, 10:53 AM
#10
Re: [2005] Showing Forms Dynamically
 Originally Posted by Tom Sawyer
Code:
Dim t As Type = Type.GetType("Project1.Form2")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
I tried this and get the exact same error message as presented in Post 6. This time it is pointing to the word Form in the Dim frm As Form line.
-
May 16th, 2008, 10:57 AM
#11
Re: [2005] Showing Forms Dynamically
Does the New method of your Form2 have any parameters? This wouldn't work if you need to add in parameters during the instantiation.
(VB/C#) is clearly superior to (C#/VB) because it (has/doesn't have) <insert trivial difference here>.
-
May 16th, 2008, 11:14 AM
#12
Re: [2005] Showing Forms Dynamically
Nope....in my entire test project, this is every single line of code I have
Code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As Type = Type.GetType("Project1.Form2")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
End Sub
End Class
-
May 16th, 2008, 11:15 AM
#13
Re: [2005] Showing Forms Dynamically
Are you entirely sure that your assembly is called Project1?
What happens if you try the code I posted?
-
May 16th, 2008, 11:18 AM
#14
Re: [2005] Showing Forms Dynamically
Atheist: Just looking at your code tells me that it will work.
However, I would prefer something that didn't hardcode the form names as forms in this project may come and go. As it is, I have loaded all the form names in a DB table that I just read into my listbox. So, if I add a new form, or delete an existing form, the only thing that I want to have to do is go into my DB table and make the appropriate adjustment.
-
May 16th, 2008, 11:22 AM
#15
Re: [2005] Showing Forms Dynamically
 Originally Posted by Atheist
Are you entirely sure that your assembly is called Project1?
From years and years of looking a VB6 and before projects, I assumed it would be called Project1, and didn't even bother to check.
Actually, new, yet to be named .NET projects are called WindowsApplication1
This works just fine
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As Type = Type.GetType("WindowsApplication1.Form2")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
End Sub
Another VB6 holdover that bites me in the butt yet again. 
Thanks guys.
-
May 16th, 2008, 12:34 PM
#16
Re: [2005] Showing Forms Dynamically
 Originally Posted by Hack
From years and years of looking a VB6 and before projects, I assumed it would be called Project1, and didn't even bother to check.
Actually, new, yet to be named .NET projects are called WindowsApplication1
This works just fine
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As Type = Type.GetType("WindowsApplication1.Form2")
Dim frm As Form = CType(Activator.CreateInstance(t), Form)
frm.Show()
End Sub
 Another VB6 holdover that bites me in the butt yet again.
Thanks guys.
I know you've marked the thread as resolved, but there's something I think worth to mention:
1. Activator.CreateInstance is very slow to compare with creating an instance of a class directly by its contructor.
2. The actual object you create in that code is of type Form2, but it is refered to just as Form. So you cannot access to any members of Form2 should you need to.
3. By combining #1 & #2, I think it's still better to use Select Case, and instantiate the appropriate form class depending on the case. The code can be longer and doesn't look as "advanced", but it'll run much better.
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
May 16th, 2008, 01:31 PM
#17
Re: [2005] Showing Forms Dynamically
 Originally Posted by stanav
3. By combining #1 & #2, I think it's still better to use Select Case, and instantiate the appropriate form class depending on the case. The code can be longer and doesn't look as "advanced", but it'll run much better.
But wouldn't that mean hard coding the forms names?
-
May 16th, 2008, 01:36 PM
#18
Re: [2005] Showing Forms Dynamically
 Originally Posted by Hack
But wouldn't that mean hard coding the forms names?
Are you not hard coding the form name here?
Code:
Dim t As Type = Type.GetType("WindowsApplication1.Form2")
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
May 16th, 2008, 01:51 PM
#19
Re: [RESOLVED] [2005] Showing Forms Dynamically
That was just a test. When I moved the code over to production it became
Code:
Dim ExistingForm As Type = Type.GetType("PaymentTracker." & lstFormNames.Text)
Dim frm As Form = CType(Activator.CreateInstance(ExistingForm), Form)
frm.Show()
-
May 16th, 2008, 01:56 PM
#20
Re: [RESOLVED] [2005] Showing Forms Dynamically
There's also the My.Forms and My.Application.OpenForms collections that may be useful. I've never used either, so I'm not sure whether or not they'd be able to apply to what you're doing.
(VB/C#) is clearly superior to (C#/VB) because it (has/doesn't have) <insert trivial difference here>.
-
May 18th, 2008, 05:58 AM
#21
Re: [RESOLVED] [2005] Showing Forms Dynamically
Thanks Tom, maybe I'll play around with those.
-
May 19th, 2008, 08:54 AM
#22
Re: [RESOLVED] [2005] Showing Forms Dynamically
Something I would check for as well is a specific interface.
this can be important if your application grows and in a diffrent namespace is a class with the same name as one of your forms...
That would be a nasty bug to find
So Define a Interface DynamicForm ande Let these Forms implement it.
Im your Dependency injector check for that Interface.
A snippet that does this but with a "foreign" assembly:
Code:
''' <summary>
''' returns an array of classes that implements interfaces of type Interface
''' Null will be return if there was no class found in this assembly that implements the specified interface
''' </summary>
Public Function InterfacedClassNames(Of ObjectInterface)() As String()
Dim classNames() As String = Nothing
For Each _class As Type In ClassTypes
Dim currentInterface As Object = _class.GetInterface(GetType(ObjectInterface).Name)
If (Not (currentInterface) Is Nothing) Then
If (classNames Is Nothing) Then
_classNamesList = New List(Of String)
_classNamesList.Add(_class.FullName)
ReDim classNames(0)
classNames(0) = _class.FullName
Else
ReDim Preserve classNames(classNames.Length)
classNames(classNames.Length - 1) = _class.FullName
_classNamesList.Add(_class.FullName)
End If
End If
Next
Return classNames
End Function
Public Function GetObjectInstance(Of ObjectInterface)()
Dim objectInstance As ObjectInterface
Dim foundClassNames() As String = InterfacedClassNames(Of ObjectInterface)()
If (Not (foundClassNames Is Nothing)) Then
If ((ClassName Is Nothing) _
OrElse (ClassName = String.Empty)) Then
If (foundClassNames.Length = 1) Then
' if there is only one class found in the assembly and there is no preconfigured classname
objectInstance = CType(MyAssembly.CreateInstance(InterfacedClassNames(Of ObjectInterface)(0)), ObjectInterface)
Else
Throw New Exception(("there are more classes implementing interface " _
+ (GetType(ObjectInterface).Name + " found in the assembly." & vbCrLf & " You should specify which class to use by using the classname attribute in t" & _
"he configuration file." & vbCrLf)))
End If
ElseIf _classNamesList.Contains(ClassName) Then
objectInstance = CType(MyAssembly.CreateInstance(ClassName), ObjectInterface)
Else
Throw New Exception(("Configured class name " _
+ (ClassName + " not found in the assembly.")))
End If
Else
Throw New Exception(("now class implementing " _
+ (GetType(ObjectInterface).Name + (" found in assembly " + Dll))))
End If
Return objectInstance
End Function
 why can't programmers keep and 31 Oct and 25 dec apart. Why Rating is Useful
for every question you ask provide an answer on another thread.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|