Fenster mit SplitContainer mittig teilen

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Fenster mit SplitContainer mittig teilen

    Und gleich das nächte :o)
    Ich habe eine einfache Form mit einem SplitContainer drauf.
    Kann ich im Designer so einstellen, dass der SplitContainer das Fenster in der Mitte teilt, egal wie groß die Form ist?
    Also so als würde ich eine Table mit zwei Spalten, die auf 50% stehen, auf meine Form schmeiße.
    Soweit ich weiß, nein. Aber wenn Du SplitterDistance anfangs auf den korrekten Wert stellst, dann IsSplitterFixed = True machst und FixedPanel bei None belässt, wird die Teilung bei Fromgrößenveränderung bei 50% beibehalten.
    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.
    @All Jou.
    @DerSmurf Was genau soll mit den Breiten passieren, wenn das Fenster gestreckt/gestaucht wird?
    Sollen beide Sub-Panels mit dem Splitter in ihrer Größe verändert werden können?
    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!
    hmm.
    Den Gedanken ein TLP zu verwenden hatte ich auch.
    Jedoch hatte ich hier das Problem, dass ich ja pro Tabellenzelle nur ein Control einfügen kann.
    Ich müsste also auf meiner TabPage ein TLP mit zwei Spalten erstellen und dann in jede der beiden Tabellenzellen wieder einen SplitContainer, oder ein anderes Control, damit ich mehrere Label anzeigen kann.
    Was spricht gegen die Lösung von @VaporiZed ?
    Das funktioniert auch.

    Edit:
    Ein TLP zum teilen. In jeder der beiden Zelle eine weitere TLP mit 1 Spalte und 2 Zeilen.
    Zeile 1 stellt die Überschrift dar ("13 offene Lieferungen"). In Zeile 2 hau ich ein Panel drauf.
    Hier kann ich dann per Code für jede offene LIeferung ein Label raufmalen und das ganze gescheit mit einer Schleife löschen, weil ich ja nur die Controls auf Panel1 durchgehen kann.
    Aber das geht ja ebenso mit einem SplitContainer in erster Ebene (also statt des TLP mit 2 50% Spalten).
    Was macht denn nu mehr Sinn?

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

    DerSmurf schrieb:

    Jedoch hatte ich hier das Problem, dass ich ja pro Tabellenzelle nur ein Control einfügen kann.
    Pack da ein normales Panel rein und Du kannst das befüllen womit immer Du willst. :thumbsup:
    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!
    Ich denke ein TLP im TLP ist schon OK.
    So habe ich die Überschrift separat, und kann mit:

    VB.NET-Quellcode

    1. For i = Me.PanelOpenOrders.Controls.Count - 1 To 0 Step -1

    Alle erstellten Labels löschen, bevor ich neue reinschreibe.
    Wenn ich die Überschrift mit ins Panel schmeiße, müsste ich diese ja nach obigem Code auch per Code erzeugen. So kann ichs im Designer.
    Den Text muss ich noch zentrieren, damits gescheit zu den (zentrierten) Überschriften passt.
    Da ich die unteren Label aber Per Code erzeuge, tue ich mich hier schwer. Wenn das Programm nicht in Vollbild läuft, siehts gut aus. Im Vollbild passt alles nicht.
    Aber ich muss ja beim Erzeugen der Labels feste Punkte angeben (wo das Label anfängt) diese sind ja anders in Vollbild und im Fenstermodus :(

    Edit: auf der linken Seite habe ich 3 einzelne Labels, auf der rechten Seite sind es 2.
    Bilder
    • Unbenannt.jpg

      104,19 kB, 1.920×1.080, 135 mal angesehen
    • soll.jpg

      321,01 kB, 1.920×1.080, 121 mal angesehen

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

    DerSmurf schrieb:

    Was macht denn nu mehr Sinn?
    Mir ist das wichtigste, dass dir das Instrumentarium bekannt ist, und du die Features verstanden hast: Layout in Windows.Forms
    Ab da musste selbst entscheiden, Entscheidungen revidieren, neu entscheiden.
    Mit TLP kann man auch so lustige Sachen machen, dass man ein 2-Teiliges TLP mit Label und Textbox fertig vorbereitet, und dann an verschiedene Stellen hinkopiert, wie mans braucht.
    Ansonsten: Ich nehme TLP wenn die Layout-Aufteilung zur Designzeit gemacht wird.
    SplitContainer nehme ich, wenn der User den Splitterbalken schieben können soll.
    (Weiters hab ich mir noch 2 ganz schnucklige ContainerControls selbst gebastelt: ein SizerPanel, das ist ein SplitContainer für mehr als zwei Spalten, und ein CaptionPanel, das ist ein Panel mit Beschriftung (oben oder links).
    Daher verwende ich SplitContainer eiglich garnimmer.)



    PS: Was ich immer sage: Controls erstellen zur Laufzeit ist Mist.
    Macht viele Umstände und Probleme, was man mit einem ListenControl (DGV, Listbox) nicht hätte.
    Was du da anzeigst würde ich in 2 datengebundenen DGVs anzeigen.
    Mag sein, sähe nicht so dolle aus, aber dafür wärs knapp und v.a. vom Datenfluss her sauber programmiert ("skalierbar").
    Sodass ich auch 50 offene Lieferungen von 20 Firmen anzeigen könnte, inklusive Bestellnummern, und sowas.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Huhu. Mit deinem P.S. hast du vollkommen recht.
    Allerdings ist mir hier die Optik schon recht wichtig (was ja sonst bei mir nicht unbedingt der Fall ist).
    Also ein gebundenes DGV kommt nicht in Frage.

    Ich habe mir mal Gedanken gemacht, wie ich das ganze mit Labels mittig auf die Form bekomme.
    In der Theorie finde ich meinen Ansatz gut, praktisch klappts aber einfach nicht.
    Es geht um die Bestellungen. Also linke Seite.

    VB.NET-Quellcode

    1. ​xPosition = CInt((Me.Width / 2 - 205 - 177 - 160) / 2)

    Me.width / 2 = halbe Formbreite
    -205 = Abstand von Label1 zu Label2
    -177 = Abstand von Label2 zu Label3
    -160 = Breite des Labels3 (rechtsbündige Textdarstellung)
    das ganze / 2 = damits dann mittig ist.

    Edit: Ja klar. Der Code funktioniert. Aber wenn ich die Größe der Form ändere, wird ja meine Sub garnicht gefeuert.
    Wenn ich von Fenstermodus in Vollbild wechsel und die Startseite neu zeichne (also die Sub manuell starte) stimmt die Darstellung.
    So klappt alles. Deine Videos zum Layouting habe ich mir angesehen. Allerdings habe ich diese bereits öfters zu gemüte geführt (und ich denke mittlerweile auch verinnerlicht)
    Btw. an dieser Stelle vielen Dank für deinen Youtube Channel! (Weiß nicht, ob ich das schon mal gesagt habe)
    Gerade beim Thema DataSet warst du viele Abende meine "Einschlaflektüre"!

    Ich habe die Sub zum erstellen der Labels jetzt auch im Form Resize Event. So ist mein Text immer schön zentriert.
    Ich poste mal den Code. Könntest du mir @ErfinderDesRades erklären, wo hier das Problem, mit den zur Laufzeit erstellten Controls ist?
    Denn ich finde meinen Code OK - allerdings bin ich ja echt der falsche um das zu beurteilen.
    Das einzige was ich negativ finde ist die Codemasse, im Vergleich zu zwei gebundenen DGVs zur Anzeige.

    Eins noch vorweg. Den Fall, dass es keine Bestellung / fehlende Rechnung gibt, habe ich beim Erstellen meines Codes vergessen.
    Das baue ich natürlich noch ein:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Sub zum anzeigen der Informationen auf Startseite
    2. Private Sub DrawHomeScreen()
    3. Dim OrderAmountTotal As Integer
    4. Dim OpenOrders As New List(Of String)
    5. Dim MissingInvoiceCountTotal As Integer
    6. Dim OpenInvoices As New List(Of String)
    7. 'Labels auf Homeseite löschen
    8. ClearHome()
    9. 'Bestellungen und Rechnungen zur Anzeige laden
    10. GetDataForHomeScreen(OpenOrders, OrderAmountTotal, OpenInvoices, MissingInvoiceCountTotal)
    11. 'Ausgabe der Daten für Lieferungen
    12. WriteDataToHomeScreen(OpenOrders, OrderAmountTotal, OpenInvoices, MissingInvoiceCountTotal)
    13. End Sub


    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Sub zum löschen der Labels auf Startseite
    2. Private Sub ClearHome()
    3. 'Bestellungen
    4. For i = Me.PanelOpenOrders.Controls.Count - 1 To 0 Step -1
    5. If TypeOf Me.PanelOpenOrders.Controls(i) Is Label Then
    6. Me.PanelOpenOrders.Controls.RemoveAt(i)
    7. End If
    8. Next
    9. 'Rechnungen
    10. For i = Me.PanelMissingInvoices.Controls.Count - 1 To 0 Step -1
    11. If TypeOf Me.PanelMissingInvoices.Controls(i) Is Label Then
    12. Me.PanelMissingInvoices.Controls.RemoveAt(i)
    13. End If
    14. Next
    15. End Sub


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub GetDataForHomeScreen(ByRef OpenOrders As List(Of String), ByRef OrderAmountTotal As Integer,
    2. ByRef OpenInvoices As List(Of String), ByRef MissingInvoiceCountTotal As Integer)
    3. Dim Orderfound As Boolean
    4. Dim DateofReceive As String
    5. Dim DaysTillArrival As Integer
    6. Dim SupplierName As String
    7. Dim MissingInvoiceCount As Integer
    8. Dim InvoiceDates As New List(Of String)
    9. 'Schleife druch jeden Lieferanten
    10. For Each Supplier In DtsSettings.Supplier
    11. Orderfound = False
    12. MissingInvoiceCount = 0
    13. DateofReceive = ""
    14. 'Bestellungen für den Lieferanten laden
    15. Dim Orders = Supplier.GetOrderRows()
    16. 'Schleife durch jede Bestellung
    17. For Each Order In Orders
    18. 'Prüfen ob Lieferdatum leer ist
    19. If Order.IsDeliveryDateNull Then
    20. If Orderfound Then
    21. SupplierName = ""
    22. Else
    23. SupplierName = Supplier.Name
    24. End If
    25. Orderfound = True
    26. OrderAmountTotal += 1
    27. 'Lieferdatum ausrechnen
    28. If Supplier.IsDeliverDurationAverageNull Then
    29. DateofReceive = "erste Lieferung"
    30. Else
    31. DateofReceive = (Microsoft.VisualBasic.DateAdd("d", CInt(Supplier.DeliverDurationAverage), Order.OrderDate)).ToShortDateString
    32. End If
    33. 'ausrechnen, wann Lieferung kommt
    34. If DateofReceive = "erste Lieferung" Then
    35. DaysTillArrival = 10000
    36. Else
    37. DaysTillArrival = CInt(Date.Parse(DateofReceive).Subtract(System.DateTime.Now).TotalDays + 1)
    38. End If
    39. 'Werte in List of string speichern
    40. OpenOrders.Add(SupplierName & "|" & DaysTillArrival & "|" & DateofReceive)
    41. Else
    42. 'wenn Lieferdatum existiert, prüfen ob Rechnung erhalten
    43. If Order.IsInvoiceReceiveNull Then
    44. MissingInvoiceCountTotal += 1
    45. MissingInvoiceCount += 1
    46. 'Datum der fehlenden Rechnungen in List of String speichern
    47. If MissingInvoiceCount > 0 Then
    48. InvoiceDates.Add(Order.OrderDate.ToShortDateString)
    49. End If
    50. End If
    51. End If
    52. Next
    53. 'fehlende Rechnungen in List of String speichern
    54. For j = 0 To MissingInvoiceCount - 1
    55. If j = 0 Then
    56. OpenInvoices.Add(Supplier.Name & "|" & MissingInvoiceCount & " vom " & InvoiceDates(j))
    57. Else
    58. OpenInvoices.Add(" " & "|vom " & InvoiceDates(j))
    59. End If
    60. Next
    61. Next
    62. End Sub


    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Sub zum schreiben der Daten auf Homescreen
    2. Private Sub WriteDataToHomeScreen(OpenOrders As List(Of String), OrderAmountTotal As Integer,
    3. OpenInvoices As List(Of String), MissingInvoiceCountTotal As Integer)
    4. 'offene Bestellungen schreiben
    5. Dim xPosition As Integer
    6. Dim yPosition = 20
    7. 'Schleife durch alle offenen Bestellungen
    8. For i = 0 To OpenOrders.Count - 1
    9. xPosition = CInt((Me.Width / 2 - 205 - 177 - 160) / 2)
    10. 'Order Info in Array speichern | Name=0, Lieferzeit=1, Ankunftsdatum=2
    11. Dim OrderInfo() As String = Split(OpenOrders(i), "|")
    12. 'Label Firmaname erstellen
    13. Dim NewLBLSupplierName As New System.Windows.Forms.Label
    14. With NewLBLSupplierName
    15. .Location = New System.Drawing.Point(xPosition, yPosition)
    16. .Font = New Font("Microsoft Sans Serif", 16)
    17. .Name = "LBL" & OrderInfo(0)
    18. .TextAlign = ContentAlignment.MiddleLeft
    19. .Size = New System.Drawing.Size(199, 26)
    20. .Text = OrderInfo(0)
    21. .Visible = True
    22. End With
    23. 'Label Menge offener Bestellungen erstellen
    24. xPosition += 205
    25. Dim NewLBLDeliverDuration As New System.Windows.Forms.Label
    26. Dim DeliverDurationText As String
    27. 'Text zur Ausgabe, wann Lieferung eintrifft erstellen
    28. Select Case Integer.Parse(OrderInfo(1).ToString)
    29. Case > 1
    30. If Integer.Parse(OrderInfo(1)) = 10000 Then
    31. DeliverDurationText = ""
    32. Else
    33. DeliverDurationText = "in " & OrderInfo(1) & " Tagen"
    34. End If
    35. Case = 1
    36. DeliverDurationText = "morgen"
    37. Case = 0
    38. DeliverDurationText = "heute"
    39. Case = -1
    40. DeliverDurationText = "gestern"
    41. Case < -1
    42. DeliverDurationText = "vor " & CInt(OrderInfo(1)) * -1 & " Tagen"
    43. End Select
    44. With NewLBLDeliverDuration
    45. .Location = New System.Drawing.Point(xPosition, yPosition)
    46. .Font = New Font("Microsoft Sans Serif", 16)
    47. .Name = "LBLDeliverDuration"
    48. .TextAlign = ContentAlignment.MiddleLeft
    49. .Size = New System.Drawing.Size(171, 26)
    50. .Text = DeliverDurationText
    51. .Visible = True
    52. End With
    53. 'Label Menge offener Bestellungen erstellen
    54. xPosition += 177
    55. Dim NewLBLArrivalDate As New System.Windows.Forms.Label
    56. With NewLBLArrivalDate
    57. .Location = New System.Drawing.Point(xPosition, yPosition)
    58. .Font = New Font("Microsoft Sans Serif", 16)
    59. .Name = "LBLArrivalDate"
    60. .TextAlign = ContentAlignment.MiddleRight
    61. .Size = New System.Drawing.Size(160, 26)
    62. .Text = OrderInfo(2)
    63. .Visible = True
    64. End With
    65. yPosition += 36
    66. 'Label auf die Form malen
    67. PanelOpenOrders.Controls.Add(NewLBLSupplierName)
    68. PanelOpenOrders.Controls.Add(NewLBLDeliverDuration)
    69. PanelOpenOrders.Controls.Add(NewLBLArrivalDate)
    70. Next
    71. 'Überschriften für Bestellungen beschreiben
    72. LBLOpenOrders.Text = OrderAmountTotal.ToString & " offene Lieferungen"
    73. 'Ausgabe der Daten für Rechnungen
    74. yPosition = 20
    75. 'Rechnungsinfo in Array speichern | Name=0, Bestelldatum=1
    76. For i = 0 To OpenInvoices.Count - 1
    77. xPosition = CInt((Me.Width / 2 - 205 - 190) / 2)
    78. Dim InvoiceInfo() As String = Split(OpenInvoices(i), "|")
    79. 'Label erstellen
    80. Dim NEWLBLInvoice As New System.Windows.Forms.Label
    81. With NEWLBLInvoice
    82. .Location = New System.Drawing.Point(xPosition, yPosition)
    83. .Font = New Font("Microsoft Sans Serif", 16)
    84. .Name = "LBLInvoice"
    85. .TextAlign = ContentAlignment.MiddleLeft
    86. .Size = New System.Drawing.Size(199, 26)
    87. .Text = InvoiceInfo(0)
    88. .Visible = True
    89. End With
    90. xPosition += 205
    91. Dim NEWLBLInvoiceDate As New System.Windows.Forms.Label
    92. With NEWLBLInvoiceDate
    93. .Location = New System.Drawing.Point(xPosition, yPosition)
    94. .Font = New Font("Microsoft Sans Serif", 16)
    95. .Name = "LBLInvoice"
    96. .TextAlign = ContentAlignment.MiddleRight
    97. .Size = New System.Drawing.Size(190, 26)
    98. .Text = InvoiceInfo(1)
    99. .Visible = True
    100. End With
    101. yPosition += 36
    102. 'Label auf die Form malen
    103. PanelMissingInvoices.Controls.Add(NEWLBLInvoice)
    104. PanelMissingInvoices.Controls.Add(NEWLBLInvoiceDate)
    105. Next
    106. 'Überschriften für Rechnungen beschreiben
    107. LBLMissingInvoices.Text = MissingInvoiceCountTotal.ToString & " fehlende Rechnungen"
    108. End Sub
    Bilder
    • dataset.jpg

      343,01 kB, 1.920×1.080, 130 mal angesehen

    DerSmurf schrieb:

    Allerdings ist mir hier die Optik schon recht wichtig.
    Also ein gebundenes DGV kommt nicht in Frage.

    Na, vlt. unterschätzst du die Gestaltungsmöglichkeiten von DGV.
    Mit bischen Hexerei kriegt man auch so gruppierten Ansichten hin, vergleichbar deiner "fehlendeRechnung"-Darstellung.

    Aber genau so wie bei dir wirds natürlich nicht (dafür annere Möglichkeiten).

    ErfinderDesRades schrieb:

    Daher verwende ich SplitContainer eiglich garnimmer.
    Ich hab iwie gemerkt, dass auf abgeleiteten Forms mit n Haufen Layout in der BaseForm nur ein SplitContainer erlaubt, weitere Unter-Panels zu gruppieren.
    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!
    @DerSmurf

    Ich stand vor einem Jahr auch vor dieser Frage.
    RodFromGermany empfiehlt gernde das DGV ;-). Ich war auch Deiner Meinung, dass das optisch "kacke" aussieht. Aber es hatte damals auch jemand ein Beispiel gepsostet, dass man das auch wirklich optisch ansprechend gestalten kann. Aber natürlich mit nicht gerade wenig Aufwand ;-).

    Ich habe mich dazu entschieden meine Oberflächen ausschließlich mit Panels zu gestalten. Im Resize und Resize-End Event der Form passe ich alle Panels manuell der Fenstergröße an. Ist zwar auch sehr viel Aufwand, aber man hat da sogar mehr Kontrolle bei der Ausgabe und kann so gut wie alles machen. Ich ging sogar so weit, dass ich nur die nötigesten Forms verwende und auch hier nur auf Panels zurückgreife die ich sichtbar oder unsichtbar mache - das ist ein erheblicher Performancegewinn bei der Anzeige.

    In der Anlage ein Screenshot von meiner ERP-Software in der IDE (ja ich weiß, da wirds manchem schwindlig ;) ).
    Bilder
    • Unbenannt-1.jpg

      2,25 MB, 3.440×1.408, 119 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    @dive26 DGV und Panels sind aber zwei sehr verschiedene Paar Schuhe.
    DGV für Tabellen, klar.
    Panels für eine Gesamt-GUI, ich präferiere da ein TableLayoutPanel, höchst selten ein FlowLayoutPanel.
    SplitContainer kann allerdings erforderlich sein, wenn Du Forms ableitest, siehe Post #12.
    Und irgendwo da in eine oder mehrere Zellen kommt dann das DGV (RowSpan, ColumnSpan und Dock = Fill).
    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!