Selbstgehäkeltes mdi-modul - passt das so?

  • VB.NET

Es gibt 49 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    hi,

    das kannste dir in dem logistiktool-projekt von mir anschauen.. unter HelpersSmallEd/WinFormHelpers/TabbedMdi.vb
    da ist dann alles für die Mdi-Steuerung enthalten (ich hatte das ja alles ausgelagert, damit man das direkt in mehrere Projekte als "Helper" einbinden kann:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections
    2. Imports System.Runtime.CompilerServices
    3. Public Module TabbedMdi
    4. Private _tabControl As TabControl
    5. Private _mdiParent As Form
    6. Private _tv As TreeView
    7. ''' <summary> Anzeigen einer ChildForm - Optional mit ControlStyling und Registrierung des DataSets, sowie verstecken des TreeView </summary>
    8. <Extension>
    9. Public Sub ShowMdiChild(mdiParent As Form, Child As Form, mdiTab As TabControl, Optional dts As DataSet = Nothing, Optional CtrlStyling As Boolean = False, Optional tv As TreeView = Nothing)
    10. _tabControl = mdiTab
    11. _mdiParent = mdiParent
    12. _tv = tv
    13. RegisterMdiHandle() ' Registrierung der Handle-Methoden
    14. With Child
    15. If .MdiParent Is mdiParent Then
    16. .Select()
    17. Else
    18. tv.TVHide
    19. If Not dts Is Nothing Then dts.Register(.Self, True) ' Optional nur mit den Helpers von ErfinderDesRades
    20. If CtrlStyling = True Then ControlStyling.StyleDGV(.Self) ' Optional: eine Erweiterung von ErfinderDesRades
    21. .WindowState = FormWindowState.Maximized ' Je nach Anwendungsfall entweder alle Childs maximiert öffnen, oder nur das 1.
    22. 'If _mdiParent.MdiChildren.Count = 0 Then .WindowState = FormWindowState.Maximized
    23. .MdiParent = _mdiParent
    24. .MinimizeBox = False ' Optional: Minimize-Boxen auf Child-Forms sind unnötig
    25. .Show()
    26. 'idiotischerweise muss der ChildForm-Menustrip, dessen Items einerseits automatisch in den Parent-Menustrip
    27. ' eingemerged werden, andererseits explizit versteckt werden - sonst verbleibt ein leerer Menustrip auffm ChildForm
    28. Child.Controls.OfType(Of MenuStrip)().SingleOrDefault()?.Hide()
    29. mdiParent.ResumeLayout()
    30. End If
    31. End With
    32. End Sub
    33. ''' <summary> Registriert die Handle-Methoden für die Steuerung der Child-Forms </summary>
    34. Private Sub RegisterMdiHandle()
    35. AddHandler _mdiParent.MdiChildActivate, AddressOf MdiChildOpen
    36. AddHandler _tabControl.SelectedIndexChanged, AddressOf Tab_SelectedIndexChanged
    37. End Sub
    38. ''' <summary> Stellt beim Schließen des Childs sicher, dass die entsprechende TabPage entfernt wird </summary>
    39. Private Sub MdiChildClose(sender As Object, e As FormClosedEventArgs)
    40. DirectCast(DirectCast(sender, Form).Tag, TabPage).Dispose()
    41. If _mdiParent.MdiChildren.Count <= 1 Then
    42. For Each tsi In _mdiParent.Controls.OfType(Of ToolStripMenuItem)()
    43. If Not tsi.Enabled Then tsi.Enabled = True
    44. Next
    45. _tv.TVshow 'wenn das letzte Child geschlossen wird, TreeView einblenden
    46. End If
    47. End Sub
    48. ''' <summary> Prüft, ob das Child bereits existiert, falls nicht wird eine neue TabPage erstellt </summary>
    49. Private Sub MdiChildOpen(sender As Object, e As EventArgs)
    50. If _mdiParent.ActiveMdiChild Is Nothing Then
    51. _tabControl.Visible = False
    52. Else
    53. Dim tp = DirectCast(_mdiParent.ActiveMdiChild.Tag, TabPage)
    54. If tp Is Nothing Then
    55. tp = New TabPage(_mdiParent.ActiveMdiChild.Text)
    56. tp.Tag = _mdiParent.ActiveMdiChild
    57. _mdiParent.ActiveMdiChild.Tag = tp
    58. _tabControl.TabPages.Add(tp)
    59. AddHandler _mdiParent.ActiveMdiChild.FormClosed, AddressOf MdiChildClose
    60. If Not _tabControl.Visible Then _tabControl.Visible = True
    61. End If
    62. _tabControl.SelectedTab = tp
    63. End If
    64. End Sub
    65. ''' <summary> Ruft beim wechseln der TabPage das entsprechende Child auf und zeigt es an</summary>
    66. Private Sub Tab_SelectedIndexChanged(sender As Object, e As EventArgs)
    67. DirectCast(_tabControl.SelectedTab?.Tag, Form)?.Select()
    68. End Sub
    69. End Module


    In Zeile 41-50 das Close, der Aufruf geht in etwa so (aus frmMain): ShowMdiChild(frmStandort, tabMdi, Dts, True, tvMain)
    Deshalb, mir ist es relativ Wurscht ob ich das Aktivieren des TSI noch mit in's Modul packe oder über ein Event auf der frmMain, jedoch kenn ich kein
    Event was das auslösen könnte wenn Childs.Count <1

    Für das Auslösen im Modul muss ich dann rekursiv meine MenuStrips nach TSI druchwühlen?

    Edit:
    hierüber bekomm ich eine "StackOverflow Exception"

    VB.NET-Quellcode

    1. Private Sub WalkThroughMS(mStrip As MenuStrip)
    2. Dim recurse As Action(Of ToolStripItemCollection) = Sub(tsic As ToolStripItemCollection)
    3. For Each tsi As ToolStripMenuItem In tsic
    4. If Not tsi.Enabled Then tsi.Enabled = True
    5. recurse(tsic) ' Selbst-Aufruf der anonymen Methode
    6. Next
    7. End Sub
    8. recurse(mStrip.Items)
    9. End Sub


    CodeTags korrigiert ~VaporiZed
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Na, ein bischen mehr als garkeine Ahnung hast du davon sicherlich.
    Ich glaube, kein einziger der in post #43 verwendeten Begriffe ist dir unbekannt: MDIParent, WithEvents, Event, Klasse, Objekt.
    Übrigens "Umbauen" nicht wörtlich verstehen - dabei entstünden ja nicht lauffähige Zustände.
    Also eine Klasse bauen mit derselben Funktionalität wie derzeit das Modul, und wenn fertig und funzt, das Modul löschen.
    Hi, ich hab nochmal eine Frage zu der Geschichte. Ich habe 2 oder mehr Childs geöffnet
    Bsp.: Mitarbeiter und Planer

    Mitarbeiter ist das aktive Child, was mir angezeigt wird. Dort rufe ich einen Dialog auf, sobald ein Dialog geöffnet wird, switcht er mir die Ansicht auf das Child Planer.
    Das soll ja so nicht sein, denn der Dialog gehört zu Mitarbeiter und da wollte ich auch gerne weiter arbeiten. Muss also immer wieder umschalten. Kann man das verhindern? Wüsste
    grad nicht wie...
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    (tl;dr)
    Ich kann das nicht nachvollziehen.

    VB.NET-Quellcode

    1. Private ReadOnly Children As New List(Of Form2)
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Dim NewChild As New Form2 With {.MdiParent = Me}
    4. Children.Add(NewChild)
    5. NewChild.Show()
    6. End Sub

    Und im ChildForm gibt's n Button, der einen Dialog öffnet. Wenn der Dialog erscheint, ändert sich das aktive ChildForm nicht. Was macht Dein Dialog-Zeige-Code noch?

    ##########

    Wird da Dein selbstverdrahtetes _tabControl.SelectedIndexChanged-Event gefeuert und ändert da was an der Selektion?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    und ändert da was an der Selektion?

    Habs grad mal durch den Debugger laufen lassen. Sobald ich einen Dialog öffne, wird MdiChildOpen gefeuert und dort ist auf einmal das zuletzt geöffnete Child als ActiveMdiChild drinnen.
    Öffne ich erst Planer und dann Mitarbeiter kann ich im Mitarbeiter-Child Dialoge öffnen, ohne das er umspringt. Bei umgekehrter Reihenfolge springt er um.
    Hab's schon mit DirectCast(tabMdi.SelectedTab?.Tag, Form)?.Activate() im Tab_SelectedIndexChanged versucht, jedoch ohne Erfolg



    Also bei der Öffnen-Reihenfolge (Mitarbeiter, Planer) dann Mitarbeiter selektieren und dort einen Dialog öffnen, verhält sich ActiveMdiChild wie folgt:
    -Mitarbeiter (richtig)
    -Planer (richtig)
    -Mitarbeiter (richtig)
    -Planer (falsch, denn hier muss Mitarbeiter stehen bleiben)
    ?(
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Da ich jetzt tatsächlich so faul bin und Dein Projekt nicht nachbauen werde: Funktioniert es denn richtig, wenn Du den MdiChildOpen-EventHandler vor Dialoganzeige abkoppelst und danach wieder anbindest?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    abkoppelst und danach wieder anbindest?

    vermutlich ja, wäre aber recht kompliziert das zu testen. Denn der komplette MDI-Code sitzt auf frmMain und den könnte ich ja höchsten sehr dirty aufrufen von frmMitarbeiter aus.
    (die Subs müssten Public und dann sowas wie RemoveHandler frmMain.MdiChildActivate, AddressOf frmMain.MdiChildOpen oder so, gefällt mir nicht mal zum Testen
    Zudem wäre es unmengen an Arbeit wenn das funzen würde, denn ich hab etliche Forms mit Dialogen :P
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: