Results 1 to 22 of 22

Thread: [RESOLVED] [2005] Showing Forms Dynamically

  1. #1

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Resolved [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?

  2. #2
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: [2005] Showing Forms Dynamically

    At the moment I cant think of anything better than this:

    VB.NET Code:
    1. Dim formName As String = "Form1"
    2.         Dim assm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
    3.         Dim frm As Form = TryCast(assm.CreateInstance(String.Format("{0}.{1}", assm.GetName.Name, formName)), Form)
    4.         If Not frm Is Nothing Then
    5.             frm.Show()
    6.         End If
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  3. #3
    Registered User nmadd's Avatar
    Join Date
    Jun 2007
    Location
    U.S.A.
    Posts
    1,676

    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:
    1. Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
    2.     Select Case Me.ListBox1.SelectedItem.ToString()
    3.         Case "Form2"
    4.             Dim f2 As New Form2()
    5.             f2.Show()
    6.         Case "Form3"
    7.             Dim f3 As New Form3()
    8.             f3.Show()
    9.     End Select
    10. End Sub

  4. #4
    Fanatic Member Dnereb's Avatar
    Join Date
    Aug 2005
    Location
    Netherlands
    Posts
    863

    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.

  5. #5
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    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>.

  6. #6

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    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
    Quote 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.

  7. #7
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    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.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  8. #8
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    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>.

  9. #9
    Lively Member
    Join Date
    May 2008
    Posts
    117

    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.

  10. #10

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: [2005] Showing Forms Dynamically

    Quote 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.

  11. #11
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    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>.

  12. #12

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    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

  13. #13
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: [2005] Showing Forms Dynamically

    Are you entirely sure that your assembly is called Project1?
    What happens if you try the code I posted?
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  14. #14

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    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.

  15. #15

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: [2005] Showing Forms Dynamically

    Quote 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.

  16. #16
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    Re: [2005] Showing Forms Dynamically

    Quote 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 -

  17. #17

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: [2005] Showing Forms Dynamically

    Quote 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?

  18. #18
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    Re: [2005] Showing Forms Dynamically

    Quote 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 -

  19. #19

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    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()

  20. #20
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    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>.

  21. #21

    Thread Starter
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: [RESOLVED] [2005] Showing Forms Dynamically

    Thanks Tom, maybe I'll play around with those.

  22. #22
    Fanatic Member Dnereb's Avatar
    Join Date
    Aug 2005
    Location
    Netherlands
    Posts
    863

    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
  •  



Click Here to Expand Forum to Full Width