2013-03-12 14 views
6

Próbuję utworzyć niestandardowy panel sterowania za pomocą własnego silnika układu. muszę każdą kontrolę, która jest dodawana do mojego panelu należy dodać poniżej i wziąć pełną szerokość (-padding), jak poniżej: enter image description herePanel niestandardowy z silnikiem układu

Poniżej jest mój kod:

using System.Drawing; 
using System.Windows.Forms; 
using System.Windows.Forms.Layout; 

namespace VContainer 
{ 
    internal class VerticalFillList : Panel 
    { 
     public VerticalFillList() 
     { 
      AutoScroll = true; 
      MinimumSize = new Size(200, 200); 
      Size = new Size(200, 300); 
      Padding = new Padding(10); 
     } 

     private readonly VerticalFillLayout _layoutEngine = new VerticalFillLayout(); 

     public override LayoutEngine LayoutEngine 
     { 
      get { return _layoutEngine; } 
     } 

     private int _space = 10; 

     public int Space 
     { 
      get { return _space; } 
      set 
      { 
       _space = value; 
       Invalidate(); 
      } 
     } 
    } 

    internal class VerticalFillLayout : LayoutEngine 
    { 
     public override bool Layout(object container, LayoutEventArgs layoutEventArgs) 
     { 
      var parent = container as VerticalFillList; 

      Rectangle parentDisplayRectangle = parent.DisplayRectangle; 
      Point nextControlLocation = parentDisplayRectangle.Location; 

      foreach (Control c in parent.Controls) 
      { 
       if (!c.Visible) 
       { 
        continue; 
       } 

       c.Location = nextControlLocation; 
       c.Width = parentDisplayRectangle.Width; 
       nextControlLocation.Offset(0, c.Height + parent.Space); 
      } 
      return false; 
     } 
    } 
} 

Powyższy kod działa poprawnie , z wyjątkiem jednej rzeczy: kiedy dodajemy kontrole do mojego kontenera, są one dodawane poprawnie (nowe poniżej rodzica, 100% szerokości), ale gdy wysokość kontrolek jest większa niż moja wysokość kontenera, otrzymuję poziome paski przewijania, ale po dodaniu kontrolek więcej paska przewijania zostanie usunięte. adding components

samo dzieje się, gdy chcę zmienić rozmiar mojego pojemnika: resizing container

Jak to może być stałe? Po prostu muszę usunąć poziomy pasek przewijania.

Oczywiście wszystkie ulepszenia są mile widziane :)

Nie chcę używać układ tabeli lub układ płynąć jak ten daje mi dokładnie, kiedy muszę.

Potrzebuję prostego pojemnika, który zamawia wszystkie elementy sterujące dla dzieci od góry do dołu i rozciąga je w poziomie, aby zajmowały tyle samo szerokości, aby poziomy pasek przewijania nie był potrzebny.

+0

ale jeżeli on być ustalony nie można umieścić wiadomości bottons zawsze ... O_O – MayogaX

+0

@MajogaX - Wiem, że :) Chciałem tylko pokazać mój punkt widzenia. Będę miał niestandardowe elementy sterujące zamiast przycisków. Chciałem pokazać, jak zachowuje się mój panel. W większości przypadków będę miał 2-3 kontrolki, ale kiedy użytkownik doda nowy, chcę uniknąć sytuacji, w której widoczny jest poziomy pasek przewijania. Ta sama sytuacja przy zmianie rozmiaru mojej aplikacji. Będę tam trzymać maksymalnie 5-6 kontrolek. Powyżej jest tylko demo, które pokazuje niechciane zachowanie. – Misiu

+2

Próbujesz rozwiązać problem, który projektanci WinForma ostrożnie przeszli w swojej klasie LayoutEngine. Takie układy są * bistabilne *. Najbardziej typowym wynikiem próby rozwiązania tego problemu jest utknięcie w nieskończonej pętli z włączonym i wyłączonym poziomym paskiem przewijania. Jesteś trochę skazany na wynurzenie klasy, a kończy się to w ten sam sposób. –

Odpowiedz

3

Oto przykład roboczych, które niestety nie wykorzystuje swoją klasę Układ silnika. To po prostu opiera się na metodach OnControlAdded i OnControlRemoved i kotwienia i ustawienie właściwości AutoScrollMinSize specjalnie upewnij się, że nigdy nie pojawia się poziomy pasek przewijania:

internal class VerticalPanel : Panel { 
    private int space = 10; 

    public int Space { 
    get { return space; } 
    set { 
     space = value; 
     LayoutControls(); 
    } 
    } 

    protected override void OnControlAdded(ControlEventArgs e) { 
    base.OnControlAdded(e); 
    LayoutControls(); 
    } 

    protected override void OnControlRemoved(ControlEventArgs e) { 
    base.OnControlRemoved(e); 
    LayoutControls(); 
    } 

    private void LayoutControls() { 
    int height = space; 
    foreach (Control c in base.Controls) { 
     height += c.Height + space; 
    } 
    base.AutoScrollMinSize = new Size(0, height); 

    int top = base.AutoScrollPosition.Y + space; 
    int width = base.ClientSize.Width - (space * 2); 
    foreach (Control c in base.Controls) { 
     c.SetBounds(space, top, width, c.Height); 
     c.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right; 
     top += c.Height + space; 
    } 
    } 
} 
+0

Layout Engine był tylko opcją, która działała całkiem dobrze, ale miałem problemy z paskiem przewijania. Jeśli Twoje rozwiązanie rozwiązuje ten problem, to jest to dla mnie idealne :) – Misiu

+1

Sprawdziłem Twoje rozwiązanie, działa jak urok :) jedyną rzeczą, którą należy dodać jest nadpisanie 'OnControlRemoved', aby wywołać' LayoutControls' aby usunąć pasek przewijania. – Misiu

-1

Można ustawić AnchorProperty na ciebie przyciski jak:

button1.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; 

Więc oni być zmieniany poziomo

+0

Nie potrzebuję zakotwiczenia dla przycisków, ponieważ mój układ graficzny obsługuje pozycję każdego komponentu w pojemniku. Przyciski wewnątrz mojego niestandardowego panelu zmieniają się poprawnie. Muszę usunąć poziomy pasek przewijania, ponieważ czasami jest widoczny. – Misiu

Powiązane problemy