Split Container und Datagrid View - dynamische Spaltenauswahl

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

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Split Container und Datagrid View - dynamische Spaltenauswahl

    Hi,

    heute habe ich ein ziemlich kniffeliges Problem. Ich hoffe, ihr habt ein wenig Geduld, weil die Sache nicht ganz so einfach zu erklären ist.

    Nehmen wir an, wir wollen einen FileBrowser schreiben. dazu benötigen wir zwei DataGrid Views, eine für die Directories und eine für die Files. Die beiden Datagrid Views packen wir in einen Split Container. Fertig ist der Lack. Im Anhang 1 habe ich ein rudimentäres Sample eingestellt.

    Die Breite des Containers beträgt 800 Einheiten, das linke Panel ist FIXED und hat eine Breite von 300 Einheiten, das rechte Panel ist VARIABEL und hat eine Breite von 496 Einheiten (weil die SplitterWidth = 4 ist). Der SplitContainer ist an die Form angedockt.

    Die Breite der FileName Spalte ist 223 Einheiten, sie ist mit AutosizeMode=Fill definiert. Als Minimale Breite sind 80 Einheiten angegeben, dass FillWeight beträgt 100.

    Die anderen Spalten haben feste Längen:

    Attr: 50 Einheiten
    Size: 80 Einheiten
    Last Changed: 140 Einheiten

    Wenn man nun die Form durch Ziehen verkleinert, dann wird das Panel2 verkleinert. Zunächst wird dabei die Spalte FileName verkleinert. (s. Anhang2)

    Der Container hat jetzt eine Width von 700 Einheiten, folgerichtig ist die Breite der Spalte Filename auf 123 gesunken.

    Wenn man die Form weiter verkleinert, wird irgendwann die minimale Breite der Spalte FileName unterschritten. (s. Anhang3)

    Der Container ist jetzt 600 Einheiten breit. Die Spalte Filename kann aber nicht auf 23 Einheiten verkleinert werden. Sie bleibt bei 80 Einheiten "stehen" und es können nicht mehr alle Spalten Daten angezeigt werden. Es erscheint am unteren Rand ein "Schieberegler".

    Und hier haben wir schon das erste Problem. Dieser Schieberegler funktioniert nicht so wie ich mir das vorstelle. Man kann das Window nur geringfügig verschieben. Daten am rechten Rand des SplitPanels können NICHT angezeigt werden!

    Bis hierhin ist die Welt aber trotzdem noch weitgehend in Ordnung. Ich hoffe, ihr habt mir bis dahin folgen können.

    Nun möchte ich aber Spalten per Check Box ein- und ausschalten können. Dazu dienen die Kästchen oberhalt des Split Containers.

    Zunächst schalten wir die Spalte "ATTR" aus. (s. Anhang4)

    Erwartungsgemäß wird der durch Attr freigegebene Platz der Spalte FileName zugeschlagen. Die Breite steigt um 50 Einheiten von 223 auf 273 Einheiten.

    Wenn man nun wieder die Form verkleinert, dann ist zunächst alles Palletti (s. Anhang 5)

    Die Breite des Containers beträgt jetzt 700 Einheiten und die Breite der Spalte FileName ist wie zu erwarten auf 173 Einheiten gesunken.

    Wenn wir aber nun die Breite weiter verkleinern, passiert etwas Merkwürdiges (s. Anhang 6)

    Die Container Breite beträgt jetzt 600 Einheiten. Die Breite der Spalte FileName sinkt aber nicht auf 80 Einheiten, sondern bleibt aber bei 127 Einheiten stehen ! Das scheint mir ein FEHLVERHALTEN zu sein. Obwohl damit die effektive minimale Breite der Spalte massiv verändert wird, bleibt die EIGENSCHAFT MinimumWidth unverändert bei 80 Einheiten !

    Es erscheint auch kein Schieberegler mehr! (Auch wenn man den nicht sonderlich vermisst, da er ohnehin nicht funktioniert). :)

    Die Symptomatik wird klar, wenn man andere Spalten ausschaltet, etwa Size und LastChanged. (s. Anhang 7)

    Die Breite der Spalte FileName bleibt jetzt bei 297 stehen (und nicht bei 80) !

    Offensichtlich wird die Breite der ausgeblendeten Spalten der Mindestbreite der Spalte Filename hinzu addiert (abzüglich von exakt 3 Einheiten). Mindestbreite Filename 80 + Breite Size 80 + Breite LastChanged 140 - 3 Einheiten = 297 Einheiten.

    Das wird auch durch das Verhalten beim Ausblenden der Spalte Attr bestätigt: Mindestbreite Filename 80 + Breite Attr 50 - 3 Einheiten = 127 Einheiten.

    Mir scheint, dass hier im .NET ein Fehler vorliegt. Aber ich würde das gern mit euch abklären, ehe ich mich daran mache, dieses Verhalten zu umgehen. Möglichweise mache ich ja auch nur irgend etwas falsch.

    Vielen Dank für eure (unendliche) Geduld und LG
    Peter
    Bilder
    • s 2017-05-01 14-33-054.jpg

      39,76 kB, 819×440, 175 mal angesehen
    • s 2017-05-01 14-33-527.jpg

      41,77 kB, 819×440, 176 mal angesehen
    • s 2017-05-01 14-34-219.jpg

      45,81 kB, 819×440, 145 mal angesehen
    • s 2017-05-01 14-35-551.jpg

      39,04 kB, 819×440, 145 mal angesehen
    • s 2017-05-01 14-36-217.jpg

      40,85 kB, 819×440, 156 mal angesehen
    • s 2017-05-01 14-36-570.jpg

      44,27 kB, 819×440, 168 mal angesehen
    • s 2017-05-01 14-44-201.jpg

      37,19 kB, 819×440, 164 mal angesehen

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Peter329“ ()

    @Peter329 Kanst Du mal ein rudimentäres GUI-Projekt davon hochladen?
    Es spielt sich besser am "lebenden Objekt". ;)
    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!
    @Peter329 Offensichtlich überlagern sich da die Breiten-Properties mehrerer Controls. Die Frage ist dann, in welcher Reihenfolge die Roles angewendet werden.
    Wenn Du das Panel1 des SplitContainers auf Fixed gesetzt hast, könntest Du auch ein TableLayoutPanel nehmen, vielleicht verhält sich das "normaler".
    Ansonsten würde ich dieses Verhalten auch als "normal" bezeichnen.
    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!
    Jau, erst mal schönen Dank ! Damit haben wir das Problem jetzt schon mal näher eingegrenzt.

    Wenn ich meine DatagridView2 aus dem SplitContainer1.Panel2 herausnehme und in eine eigene GroupBox stelle, dann verhält sie sich auch vollkommen "normal" ! Man kann die Spalten ein- und ausblenden ... wenn man die GroupBox verkleinert, wird die Spalte Filename bis zum Minimum von 80 Einheiten verkürzt. Wenn man dann noch weiter verkleinert, werden die verbliebenen Spalten angeknabbert und ein Schieberegler wird eingeblendet, der auch funktioniert. Also alles genauso, wie man sich das vorstellt!

    Aber stell doch mal Deine DatagridView3 in den SplitContainer1.Panel2 mit Dock=Fill hinein. Und schon verhält sich auch die DataGridView3 absolut "schweinisch", wenn man dynamisch (also per Programmcode) eine oder mehrere Spalten AUSBLENDET! :)

    Wenn man alle Spalten wieder anzeigt, verschwinden die Probleme. Aber sobald man auch nur eine Spalte wieder ausblendet, verhält sich das Dingens abnormal (Test: Button "Toggle dgv3")

    Ich hab keine Ahnung, warum das im SplitContainer so schief läuft ...

    LG
    Peter
    Dateien

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

    @Peter329 Probier mal, nach der Veränderung der Spaltenanzahl "mit Gewalt" ein Resize für den Container auszulösen, indem Du die Form um ein Pixel breiter und wieder schmaler machst (damit die Breite nicht verändert wird).
    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 hab die Form und die GroupBox nach diesem Muster angesprochen ...

    VB.NET-Quellcode

    1. Dim myFormSize As Size = Me.Size
    2. myFormSize.Width += 1
    3. Me.Size = myFormSize
    4. myFormSize.Width -= 1
    5. Me.Size = myFormSize
    6. Dim myGroupBoxSize As Size = GroupBox1.Size
    7. myGroupBoxSize.Width += 1
    8. GroupBox1.Size = myGroupBoxSize
    9. myGroupBoxSize.Width -= 1
    10. GroupBox1.Size = myGroupBoxSize


    Das Size-Event der dgv wird dadurch ausgelöst

    VB.NET-Quellcode

    1. Private Sub DataGridView3_SizeChanged(sender As Object, e As EventArgs) Handles DataGridView3.SizeChanged
    2. MessageBox.Show("New dgvSize=" & DataGridView3.Size.ToString)
    3. End Sub


    Aber am Verhalten der dgv ändert sich dadurch leider nix.
    Irgendwie stimmt das Zusammenspiel zwischen den Controls "SplitContainer" und "DataGridView" nicht, wenn man Spalten in der dgv dynamisch ausschaltet.

    Das ist blöde, denn so eine Funktionalität wäre ja schon sehr wünschenswert.

    Folgendes habe ich versucht:

    - DataGridView3.Refresh()

    - SplitContainer.Panel2 + GroupBox + DataGridView (d.h. die dgv noch einmal in eine GroupBox verpackt)

    - In allen Controls Dock=Fill durch Dock=None und Anchor=TopBottomLeftRight ersetzt.

    - Ich habe alle Eigenschaften des SplitContainer und der DataGridView "durchgehechelt".

    Es hilft alles nichts. Ich habe nichts gefunden was das Problem beheben würde.

    Ich hab das Gefühl, dass ich mit meinem Latein am Ende bin. Und leider fällt mir auch nichts Sinnvolles ein, wie ich dieses Problem umgehen könnte.

    Na, vielleicht hat ja jemand doch noch eine schlaue Idee.

    LG
    Peter
    @Peter329 Hat das DGV seine Größe ebenfalls verändert oder nicht?
    Falls nicht, mach mal das Prozedere mit dem DGV.
    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!
    Die Größe der dgv ändert sich. Solange, bis die MinimumWidth der Spalte Filename (also 80 Einheiten) erreicht ist. Und das ist ja auch richtig so.

    Wenn ich aber Spalten dynamisch ausblende, dann wird die Breite der AUSGEBLENDETEN Spalten dieser MinimumWidth HINZUGEFÜGT ! Warum auch immer.

    Und damit ist das Display Verhalten der Spalte Filenname falsch - die angezeigt minimale Breite ist nun viel zu groß.

    Merkwürdigerweise enthält die Eigenschaft MinimumWidth der Spalte trotzdem immer noch den "richtigen" Wert, nämlich 80 Einheiten. Irgendwie kommt die Steuerung der Control hier ins Schleudern.

    Man müsste vielleicht nach dem Ausblenden von Spalten die DataGridView neu instanzieren ... Die dgv mit .Dispose zu entfernen ist ja kein Problem - aber wie kann ich das Dingens wieder erstellen ?

    Peter329 schrieb:

    dann wird die Breite der AUSGEBLENDETEN Spalten dieser MinimumWidth HINZUGEFÜGT
    Hab da so ein dunkles Gefühl.
    Die Spaltenbreite kannst Du ja vorgeben, auch, ob sie fix oder vaiabel ist.
    Kann es sein, dass die breiter werdende Spalte eine variable Breite hat?
    Im Ernstfall machst Du die alle fix und hängst eine variable Dummispalte rechts außen dran.
    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!
    Erst mal wie immer herzlichen Dank für deine Ideen!

    Ich habe jetzt herausgefunden, wo das Problem liegt. Die Lösung lautet schlicht und ergreifend:

    SplitContainer1.Panel2MinSize = 0

    Warum ist das so:

    Die Idee, die Breite des zweiten SplitContainer Panels mindestens auf die Breite der (nicht ausblendbaren) Spalte FileName zu begrenzen ist ja verständlich. Leider klappt das auf diese Weise nicht!

    Nehmen wir an, wir haben die Panel2Minsize auf etwa 200 gesetzt. Wenn man die Form verkleinert dann wird irgendwann die minimale Breite des Panels unterschritten! Und deshalb rutscht das Panel und damit auch die dgv aus der Form heraus! Und weil das so ist, wird die dgv beim weiteren Verkleinern der Form nicht mehr "mitgenommen". Mit anderen Worten die Breite der Spalte Filename verändert sich nicht mehr, obwohl sie aufgrund der FileName.Minsize noch verkleinert werden könnte. Aus diesem Grunde wird auch kein Schieberegler mehr angezeigt. Oder der Schieberegeler wird nur teilweise angezeigt ... und damit sieht das so aus, als würde er nicht richtig funktionieren! So erklären sich die merkwürdigen Effekte, insbesondere das "Aufaddieren" der ausgeblendeten Spalten auf die Breite der Spalte Filename! Die Dinge sind eben nicht so wie sie scheinen ! :)

    Um die Breite des zweiten SplitContainer Panels zu kontrollieren, darf man NICHT die Panel2MinSize verwenden, sondern man muss die MinSize der FORM entsprechend kontrollieren. Wenn man Spalten der dgv ausblendet, sollte man die MinSize der Form entsprechend herabsetzen, wenn man Spalten wieder einblendet, sollte die MinSize der Form wieder heraufgesetzt werden. Dann verhält sich das Konstrukt "anständig".

    Das sollte man wissen, wenn man so einen Dialog programmieren möchte.

    Problem gelöst ! Danke an die Ratgeber !

    LG
    Peter

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