Announcement

Collapse
No announcement yet.

Fenster nicht mehrfach öffnen (shared)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Fenster nicht mehrfach öffnen (shared)

    Hallo,
    ist eigentlich ne Anfängerfrage, aber ich bekomms einfach nicht hin:
    Hab in einem Projekt ein Form (nenne es mal myForm), auf das aus mehreren anderen Projekten zugegriffen wird. Damit nicht jedesmal ein neues myForm aufgemacht wird, wollte ich es statisch machen. Und das macht mir Probleme. Wenn ich ein
    Shared Sub New()
    mache, funktioniert das InitializeComponent() nicht ("auf einen Instanzmember kann nicht ... verwiesen werden).
    Muss ich mir eine statische Hilfsklasse schreiben, die myForm nur dann öffnet, wenn es noch nicht offen ist?
    Danke für eine Hilfe. Norbert

  • #2
    Ja du mußt dir ein Hilfskonstrukt basteln. Im allgemeinen gibt es dafür diverse Singelton Pattern. Im speziellen kommt es drauf an was du genau brauchst. Es macht einen Unterschied ob nur eine Instanz der Klasse existieren darf oder beliebig viele und nur immer genau eine darf angezeigt sein.

    Comment


    • #3
      Danke Ralf,
      schnell wie immer und eine große Hilfe! Kann gar nicht mehr zählen, wie oft Deine Lösungen schon in unserer Software Einzug gehalten haben.
      Habs jetzt mit einer Helper-Klasse gelöst, da ich trotz intensiver Beschäftigung mit "Singelton" nicht dahinterkomme, wie man das anwendet.
      Kannst Du meine Lösung so gelten lassen:

      Code:
      Public Class frmMedAttribute
         Public Sub FillControls()
             Me.Show
             ...
         End Sub
      End Class
      
      Public Class CAttribute
          Private Shared fAttribute As frmMedAttribute
      
          Public Sub AttributeOpen()
              If fAttribute Is Nothing Then
                  fAttribute = New frmMedAttribute
              End If
          End Sub
      
          Public Sub PopulateForm()
              fAttribute.FillControls()
          End Sub
      End Class
      Ich kann von überall ein
      dim att As CAttribute = New CAttribute machen und mein Formular mit att.AttributeOpen / att.PopulateForm mein Formular befüllen.

      Comment


      • #4
        Um das tatsächlich beurteilen zu könne fehlen mir VB.Net Kenntnisse.
        Ich kann nur versuchen meine C# Kenntnisse nach VB zu ~transformieren~.

        Gefühlt ist es komisch dafür eine andere Klasse zu bemühen ich hätte statische/shared Methoden der Form hinzugefügt.

        [HIGHLIGHT=VB.Net]Public Class frmMedAttribute
        Private Shared fAttribute As frmMedAttribute
        Public Shared Sub ShowInstance()
        If fAttribute Is Nothing Then
        fAttribute = New frmMedAttribute
        End If
        If Not fAttribute.Visible Then
        fAttribute.Show()
        Else
        fAttribute.BringToFront()
        End If
        End Sub

        Public Shared Sub HideInstance()
        If fAttribute IsNot Nothing AndAlso fAttribute.Visible Then
        fAttribute.Hide()
        End If
        End Sub

        Public Shared Sub CloseInstance()
        If fAttribute IsNot Nothing Then
        HideInstance()
        fAttribute.Close()
        fAttribute = Nothing
        End If

        End Sub
        End Class[/HIGHLIGHT]

        Code ist mit Vorsicht geniessen. Ich habe meinen C# Gedankengang nach VB.Net übersetzt.
        Im Code dann halt nur noch diese 3 Methoden verwenden.

        [HIGHLIGHT=VB.Net]frmMedAttribute.ShowInstance()
        frmMedAttribute.HideInstance()
        frmMedAttribute.CloseInstance()[/HIGHLIGHT]

        Die eigentlichen Methoden, wie zum Beispiel den Konstruktor der Form kann man leider nicht sinnvoll verstecken um zu verhindern das im Code doch jemand dran vorbei arbeitet. Dann würde auch der Winforms Designer nicht mehr funktionieren.

        Comment


        • #5
          Vielen vielen Dank! Ja, das ist echter astreiner VB-Code, denke ich. Das funktioniert bestimmt.
          Wenn ich jetzt das Formular aus verschiedenen Projekten heraus aufrufen will, dann muss ich wohl schreiben
          Code:
          Dim fAtt as frmMedAttribute = New frmMedAttribute
          fAtt.ShowInstance()
          fAtt.FillControls
          Oder geht das anders? Können dann mehrere Klassen parallel auf dasselbe Form zugreifen? Oder muss ich das verhindern, indem ich zuvor immer erst ein CloseInstance() mache?

          Nun muss ich noch herausfinden, wo ich die Eigenschaften (Properties) übergebe, mit denen ich die Controls (Textboxen, Radiobuttons ...) fülle. Also z.B.
          Code:
              Public WriteOnly Property AttrPZN As String
                  Set(value As String)
                      fAttribute.aPZN = value
                  End Set
              End Property
          Komme erst morgen wieder dran. Kannst Du da nochmal helfen?

          Comment


          • #6
            Wenn ich jetzt das Formular aus verschiedenen Projekten heraus aufrufen will, dann muss ich wohl schreiben
            Nein? Du mußt keine Instanz erzeugen (kein new) einfach die Methoden an der Klasse aufrufen. Die sind shared also unabhängig von einer konkreten Instanz die hängen an der Klasse.
            Können dann mehrere Klassen parallel auf dasselbe Form zugreifen?
            Ja aber nur über die bereitgestellten Methoden. Die benutzte Instanz der Klasse ist ja in der Klasse versteckt. CloseInstance habe ich eher dafür gedacht um am Ende der Anwendung aufzuräumen.
            In normalen Betrieb sollte ShowInstance/HideInstance das Einzige sein das man braucht.
            Nun muss ich noch herausfinden, wo ich die Eigenschaften (Properties) übergebe,
            Schreib eine Methode über die du eine Klasse mit den Daten an die Form übergeben kannst. Z.b könnte man die gezeigte ShowInstance Methode so erweitern das man die Datenklasse als Parameter mit übergibt.
            Das könnte man dann so machen, falls die Form noch offen ist und andere Daten anzeigt, die angezeigten Daten durch die Übergebenen ersetzt werden und die Form ansonsten einfach weiter angezeigt wird.

            Comment


            • #7
              Das ist für mich leider nicht zu handeln. Das ist nur was für Profis.

              Code:
              Private Shared fAttribute As frmMedAttribute
                  Public Shared Sub ShowInstance()
                      If fAttribute Is Nothing Then
                          fAttribute = New frmMedAttribute
                      End If
                      If Not fAttribute.Visible Then
                          fAttribute.Show()
                      Else
                          fAttribute.BringToFront()
                      End If
                  End Sub
              Beim zweiten Aufruf knallt es beim .Show
              error.jpg

              Meine Properties kann ich von außen nicht setzen, obwohl sie Public sind. Müsste sie wahrscheinlich alle statisch machen?
              Die Eigenschaften und Methoden werden mir in anderen Projekten von der IntelliSense nicht angezeigt. Nur wenn ich vorher ein New mache. Ich kann sie aber per Hand hinschreiben und der Compiler frisst das auch. Ich glaube fast nicht, dass ich das hinbekomme. Ich schick Dir eine PN.

              Comment


              • #8
                Mit den von mir gezeigten Methoden sollte das nicht möglich sein. Dei Fehlermeldung bekommst du eigentlich nur wenn die Form disposed wurde. Entweder hast du explizit Dispose an der Form aufgerufen oder z.B. ein ShowModal eingestreut.
                Simpelst Beispiel im Anhang.

                WindowsApplication4.zip

                Comment


                • #9
                  Mache weder ein Dispose noch ein ShowModal. Werde demnächst mal mit Deinem Code herumexperimentieren.
                  Vielen Dank!
                  Norbert

                  Comment

                  Working...
                  X