Hinzufügen von doppelten TapPages verhindern

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    Hinzufügen von doppelten TapPages verhindern

    Hi,
    ich füge zur Laufzeit meinem leeren Tabcontrol neue Tappages hinzu, dazu habe ich folgenden Code:

    VB.NET-Quellcode

    1. 'Code von @'ErfinderDesRades', abgewandelt von UserControl auf RichtextBox
    2. <Extension()>
    3. Public Sub AddRTBControls(tc As TabControl, tn As TreeNode, ParamArray rtbs() As RichTextBox)
    4. tc.SuspendLayout()
    5. For i = 1 To rtbs.Length
    6. Dim rtb = rtbs(i - 1)
    7. Dim txt = If(TryCast(tn.Tag, String), "Untitled-" & i)
    8. Dim tp = New TabPage With {.Text = txt}
    9. tp.Controls.Add(rtb)
    10. tc.TabPages.Add(tp)
    11. tc.SelectTab(tp.TabIndex)
    12. Next
    13. tc.ResumeLayout()
    14. If Not tc.Visible Then tc.Visible = True
    15. End Sub


    jetzt versuche ich, das keine Tappage doppelt hinzugefügt wird.
    Mein Problem ist, das ich im Moment nicht sehe, wie ich verhindern kann, das die gleiche Tappage noch einmal hinzugefügt wird.
    Ich erstelle beim Laden der Form ein TreeView mit Einträgen aus einem Dataset. (Main TabelleName ist der Root Node, Einträge der Main Tabelle(Bezeichnung) ist der Node und Child Einträge(Info) der Main Tabelle sind die Subnode)
    Klicke ich auf einen Subnode, soll eine neue TP hinzugefügt werden.

    VB.NET-Quellcode

    1. Private Sub tvMain_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles tvMain.AfterSelect
    2. Dim rtb As New RichTextBox With
    3. {.Dock = DockStyle.Fill,
    4. .BackColor = Color.DimGray,
    5. .ForeColor = Color.WhiteSmoke,
    6. .Text = Dts.Snippet.GetSnippetText(e.Node.Text),
    7. .BorderStyle = BorderStyle.None,
    8. .Font = New Font("Segeo UI", 10)}
    9. tcSnippet.AddRTBControls(e.Node, rtb)
    10. End Sub

    ich hab mehrere Varianten versucht, komme leider nicht dahinter :(

    VB.NET-Quellcode

    1. 'versucht
    2. If tc.TabPages.IndexOf(tp) > 1 Then tc.TabPages.Remove(tp)
    3. 'versucht
    4. If tc.TabPages.ContainsKey(tp.Text) Then tc.TabPages.Remove(tp)

    Hat jemand nen Tip für mich?
    2. Frage:
    Wie kann ich im der AfterSelect Event verhindern, das auch bei Klick auf den Node der Code ausgeführt wird? Die Tabpage soll nur hinzugefügt werden, wenn ich auf den Subnode drücke.
    Danke Euch
    Grüße
    Micha

    EDIT:
    habs jetzt auch mal mit einem HashSet(Of TapPage) versucht.
    Das Hashset added ja nur, wenn das Element noch nicht vorhanden ist, richtig?
    Dann versteh ich nicht, wieso es nicht klappt :(

    VB.NET-Quellcode

    1. Private _LstTapPage As New HashSet(Of TabPage)
    2. If _LstTapPage.Add(tp) Then tc.TabPages.Add(tp) : tc.SelectTab(tp.TabIndex)

    Ich vermute, das HashSet kann die TapPages nicht unterscheiden. Wie unterscheide ich die denn?

    "Hier könnte Ihre Werbung stehen..."

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MichaHo“ ()

    Ich mache das so:

    VB.NET-Quellcode

    1. Dim tab = New TabControl.TabPageCollection(DeinTabControlInDeinerForm)
    2. If tab.Contains(DeineTabPage) Then tab.Remove(DeineTabPage) 'eine TabPage entfernen
    3. If Not tab.Contains(DeineTabPage) Then tab.Add(DeineTabPage) 'eine TabPage hinzufügen

    Hi @VB1963:
    hab es jetzt so abgeändert:

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Sub AddRTBControls(tc As TabControl, tx As String, ParamArray rtbs() As RichTextBox)
    3. tc.SuspendLayout()
    4. Dim tcc As New TabControl.TabPageCollection(tc)
    5. For i = 1 To rtbs.Length
    6. Dim rtb = rtbs(i - 1)
    7. Dim txt = If(tx, "Untitled-" & i)
    8. Dim tp = New TabPage With {.Text = txt}
    9. tp.Controls.Add(rtb)
    10. If tcc.Contains(tp) Then tcc.Remove(tp) : Else tcc.Add(tp)
    11. tc.SelectTab(tp.TabIndex)
    12. Next
    13. tc.ResumeLayout()
    14. If Not tc.Visible Then tc.Visible = True
    15. End Sub

    Die Pages werden dennoch doppelt hinzugefügt bzw. so oft wie ich auf den Subnode drücke
    P.S. das Problem, das nur das Subnode das Event auslöst hab ich übrigens schon gelöst.

    EDIT: hängt an dem New TabControl.TabCollection.... aber wo deklariere ich es dann?
    EDIT2:
    ich habe jetzt Die TabCollection ausgelagert
    In der Form Klasse: Private tcc As TabControl.TabPageCollection im Form_Load: tcc = New TabControl.TabPageCollection(tcSnippet)
    Event:

    VB.NET-Quellcode

    1. Private Sub tvMain_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles tvMain.AfterSelect
    2. If e.Node.Tag.ToString.StartsWith("Project") Then Return
    3. Dim rtb As New RichTextBox With
    4. {.Dock = DockStyle.Fill,
    5. .BackColor = Color.DimGray,
    6. .ForeColor = Color.WhiteSmoke,
    7. .Text = Dts.Snippet.GetSnippetText(e.Node.Text),
    8. .BorderStyle = BorderStyle.None,
    9. .Font = New Font("Segeo UI", 10)}
    10. tcc.AddRTBControls(tcSnippet, e.Node.Text, rtb)
    11. End Sub

    und die Extension dazu:

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Sub AddRTBControls(tcc As TabControl.TabPageCollection, tc As TabControl, tx As String, ParamArray rtbs() As RichTextBox)
    3. tc.SuspendLayout()
    4. For i = 1 To rtbs.Length
    5. Dim rtb = rtbs(i - 1)
    6. Dim txt = If(tx, "Untitled-" & i)
    7. Dim tp = New TabPage With {.Text = txt}
    8. tp.Controls.Add(rtb)
    9. If tcc.Contains(tp) Then tcc.Remove(tp) : Else tcc.Add(tp)
    10. tc.SelectTab(tp.TabIndex)
    11. Next
    12. tc.ResumeLayout()
    13. If Not tc.Visible Then tc.Visible = True
    14. End Sub

    Ich sitze glaub schon zu lange dran, finde den Fehler einfach nicht, die gleichen Pages kommen trotzdem so oft wie ich drücke

    "Hier könnte Ihre Werbung stehen..."

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „MichaHo“ ()

    Ich mache das mit Controls, die im Formseditor generiert werden. Da ist z.B. das TabPage-Control schon fertig. Dort funktioniert das...
    Versuche es einmal so in deiner Schleife. Vergib deiner neuen Page einen Namen und überprüfe, ob diese schon in der Collection vorhanden ist.
    (ich habe dazu auf die Schnelle Labels verwendet...)

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Sub addPages(tc As TabControl, ParamArray lbl() As Label)
    3. tc.SuspendLayout()
    4. Dim tcc As New TabControl.TabPageCollection(tc)
    5. For i = 0 To lbl.Length - 1
    6. Dim txt = "Page" & i
    7. Dim tp = New TabPage With {.Name = lbl(i).Text, .Text = lbl(i).Text}
    8. Dim found = False
    9. For Each y As TabPage In tcc
    10. If y.Name = tp.Name Then found = True : Exit For
    11. Next
    12. If Not found Then
    13. tcc.Add(tp)
    14. tp.Controls.Add(lbl(i))
    15. lbl(i).Location = New Point(10, 10)
    16. End If
    17. tc.SelectTab(tp.TabIndex)
    18. Next
    19. tc.ResumeLayout()
    20. If Not tc.Visible Then tc.Visible = True
    21. End Sub
    Hi,
    das funktioniert natürlich bestens.
    Hatte den Denkfehler in der Schleife weil ich am Ende erst geprüft habe ob es die Tap gibt.
    Hab mich aber nur auf den text bezogen, der wird ja eh zugewiesen.
    Das mit dem UserControl versuche ich später, muss mich da erst mal richtig einlesen.
    Jetzt geh ich aber erstmal schwimmen mit dem Kleinen.
    Danke Dir, bis später
    "Hier könnte Ihre Werbung stehen..."
    Edit:

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Sub addPages(tc As TabControl, ParamArray lbl() As Label)
    3. tc.SuspendLayout()
    4. Dim tcc As New TabControl.TabPageCollection(tc)
    5. For i = 0 To lbl.Length - 1
    6. Dim txt = "Page" & i
    7. Dim tp = New TabPage With {.Name = lbl(i).Text, .Text = lbl(i).Text}
    8. If Not tcc.ContainsKey(tp.Name) Then
    9. tcc.Add(tp)
    10. tp.Controls.Add(lbl(i))
    11. lbl(i).Location = New Point(10, 10)
    12. End If
    13. tc.SelectTab(tp.TabIndex)
    14. Next
    15. tc.ResumeLayout()
    16. If Not tc.Visible Then tc.Visible = True
    17. End Sub
    ist noch besser...
    Ich wunderte mich, wieso Contains nicht gehen sollte - einfach KontainsKey verwenden...

    MichaHo schrieb:

    Hatte den Denkfehler in der Schleife weil ich am Ende erst geprüft habe ob es die Tap gibt.
    Wenn ich Dein Problem richtig verstanden habe, musst Du einmal die Instanzen selbst prüfen, zum anderen die Namen der Tabs. Beides funktioniert:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. ' Hinzufügen derselben Instanz
    3. Me.TabControl1.Controls.Add(Me.TabPage1)
    4. End Sub
    5. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    6. Dim tp = New TabPage
    7. tp.Text = "bla"
    8. ' Hinzufügen einer neuen Instanz mit demselben Text
    9. Me.TabControl1.Controls.Add(tp)
    10. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @VB1963: JETZT weis ich auch, WO die ganze Zeit mein Fehler war....
    Weil den Cjeck auf ContainsKey hatte ich auch, aber eben so If tcc.ContainsKey(tp.Text) Then Return und das ging nicht.
    Der wichtige Hinweis ist dieser: With {.Name = lbl(i).Text
    ContainsKey will zwingend den Namen der TabPage und nicht den Text.
    SO funktioniert es für mich soweit ganz gut

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Sub AddRTBControls(tc As TabControl, tx As String, ParamArray rtbs() As RichTextBox)
    3. tc.SuspendLayout()
    4. Dim tcc As New TabControl.TabPageCollection(tc)
    5. For i = 0 To rtbs.Length - 1
    6. Dim txt = If(tx, "Untitled-" & i)
    7. Dim tp = New TabPage With {.Text = txt, .Name = txt, .TabIndex = i}
    8. tp.Controls.Add(rtbs(i))
    9. If Not tcc.ContainsKey(tp.Name) Then tcc.Add(tp)
    10. tc.SelectTab(tp.TabIndex)
    11. Next
    12. tc.ResumeLayout()
    13. If Not tc.Visible Then tc.Visible = True
    14. End Sub

    bis auf die Tatsache, das das gerade erstellte oder schon vorhandene Tab NICHT selektiert wird.... da muss ich nochmal dran rum basteln.

    EDIT: sorry @RodFromGermany erst nachm Schreiebn deinen Post gesehen :)
    "Hier könnte Ihre Werbung stehen..."