Zawijanie wyrazów dla etykiety w formularzach Windows Forms


Odpowiedzi:


166

Szybka odpowiedź: wyłącz AutoSize .

Dużym problemem jest to, że etykieta nie zmieni automatycznie wysokości (tylko szerokość). Aby uzyskać to prawo, należy podklasować etykietę i uwzględnić logikę zmiany rozmiaru w pionie.

Zasadniczo w OnPaint musisz zrobić:

  1. Zmierz wysokość tekstu (Graphics.MeasureString).
  2. Jeśli wysokość etykiety nie jest równa wysokości tekstu, ustaw wysokość i zwróć.
  3. Narysuj tekst.

Będziesz także musiał ustawić flagę stylu ResizeRedraw w konstruktorze.


12
Wybierz etykietę, do której dynamicznie dodajesz tekst. Spójrz na właściwości etykiety i wyłącz AutoSize. Teraz będziesz mógł przeciągnąć / ustawić obszar etykiety i automatycznie zawinie się, aby pozostać w tych parametrach. Nie ma potrzeby dodatkowego kodowania.
madeFromCode

Właśnie tego szukałem, ponieważ dotyczy to formatowania mojego formularza tekstem wyjaśniającym w formie akapitu.
Philip Brack

1
@madeFromCode Musisz ustawić wysokość programowo, jeśli chcesz, aby etykieta rozwijała się w pionie, inaczej tekst zostanie przycięty.
Edwin,

348

W rzeczywistości zaakceptowana odpowiedź jest niepotrzebnie skomplikowana.

Jeśli ustawisz etykietę na AutoSize, będzie ona automatycznie powiększać się z każdym umieszczonym w niej tekstem. (Obejmuje to wzrost pionowy).

Jeśli chcesz, aby zawijał słowa o określonej szerokości, możesz ustawić właściwość MaximumSize.

myLabel.MaximumSize = new Size(100, 0);
myLabel.AutoSize = true;

Testowane i działa.


10
Jeśli masz etykietę przyciąganą do kontenera, możesz wyłączyć AutoSize, pozostawić właściwość maksymalnego rozmiaru bez zmian i zawija słowa dokładnie tak, jak chcemy. KISS w pracy!
TheBlastOne

Dzięki temu rozwiązaniu nie można uzyskać szerokości płynu.
Robin

1
@Sam: Tak, po prostu ustaw odpowiednie właściwości „anchor”. Próbowałeś nawet?
John Gietzen,

1
Sam: powinieneś być w stanie ustawić Dockwłaściwość zarówno etykiety, jak i panelu na Top, zamiast mojego rozwiązania.
John Gietzen

2
Przyłączyłem się do OnResizerodzica i zadzwoniłemmyLabel.MaximumSize = new Size(Bounds.Width, 0);
Chris Morgan

23

W moim przypadku (etykieta na panelu) ustawiam label.AutoSize = falsei label.Dock = Fill. Tekst etykiety jest automatycznie zawijany.


To powoduje, że etykieta wypełnia cały formularz i powoduje, że zasłania wszystkie inne elementy sterujące w formularzu ... To znaczy, że nie działa. Czy istnieją inne wymagania, które nie wypełnią całego formularza?
Peter Mortensen

5
etykieta znajduje się na panelu , a nie bezpośrednio w formularzu. Dlatego tekst nie wykracza poza granice panelu
alex555

OK, ale czy nie zasłoniłoby to wszystkich innych elementów sterujących w panelu?
Peter Mortensen

1
Co uniemożliwia Ci utworzenie dodatkowego panelu zawierającego tylko etykietę?
alex555

To wygląda na dodatkowy układ, który powinien być niepotrzebny. Z pewnością etykieta powinna mieć własne pudełko, a nie musi być umieszczana w innym pudełku.
Edwin,

17

Zła wiadomość: nie ma właściwości automatycznego zawijania.

Dobra wiadomość: na końcu tunelu jest światło!

Możesz to zrobić programowo, aby dynamicznie dopasować rozmiar, ale oto najprostsze rozwiązanie:

  • Wybierz właściwości etykiety
  • AutoSize = True
  • MaximumSize = ( szerokość , wysokość ) gdzie Width = maksymalny rozmiar, jaki ma być etykieta, a Height = liczba pikseli, które mają być zawijane

    Przykładowe właściwości


4
Jeszcze jedna uwaga, jeśli pozostawisz maksymalną wysokość na 0, nadal będzie się rozszerzać w pionie.
palehorse

Moja etykieta nie ma właściwości AutoSize i MaximumSize, jak mogę je dodać?
mrbengi

11

Z MSDN , automatycznie zawijaj tekst w etykiecie :

using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

public class GrowLabel : Label {
    private bool mGrowing;
    public GrowLabel() {
        this.AutoSize = false;
    }
    private void resizeLabel() {
        if (mGrowing) 
            return;
        try {
            mGrowing = true;
            Size sz = new Size(this.Width, Int32.MaxValue);
            sz = TextRenderer.MeasureText(this.Text, this.Font, sz, TextFormatFlags.WordBreak);
            this.Height = sz.Height;
        }
        finally {
            mGrowing = false;
        }
    }
    protected override void OnTextChanged(EventArgs e) {
        base.OnTextChanged(e);
        resizeLabel();
    }
    protected override void OnFontChanged(EventArgs e) {
        base.OnFontChanged(e);
        resizeLabel();
    }
    protected override void OnSizeChanged(EventArgs e) {
        base.OnSizeChanged(e);
        resizeLabel();
    }
}

Aby rozdzielić znaki zamiast słów (przydatne, gdy masz długie ciągi bez spacji, takie jak ścieżki plików), zamiast tego użyj (TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl). Zobacz ostatni post w tym samym wątku MSDN.
Ohad Schneider

1
Nie zapomnij również uwzględnić górnej i dolnej części etykiety w obliczeniach ( Height = sz.Height + Padding.Vertical;)
Igor Brejc,

6

Musiałem znaleźć szybkie rozwiązanie, więc po prostu użyłem TextBox o tych właściwościach:

var myLabel = new TextBox
                    {
                        Text = "xxx xxx xxx",
                        WordWrap = true,
                        AutoSize = false,
                        Enabled = false,
                        Size = new Size(60, 30),
                        BorderStyle = BorderStyle.None,
                        Multiline =  true,
                        BackColor =  container.BackColor
                    };

To dobre rozwiązanie, ale wolę używać ReadOnly niż ustawienie Enabled na false.
PahJoker

1
To pomysłowe rozwiązanie, które działa również dobrze w Compact Framework (gdzie Label nie ma właściwości AutoSize i MaximumSize).
Tim Coulter

3

Miej lepszy na podstawie odpowiedzi @hypo

public class GrowLabel : Label {
    private bool mGrowing;
    public GrowLabel() {
        this.AutoSize = false;
    }
    private void resizeLabel() {
        if (mGrowing)
            return;
        try {
            mGrowing = true;
            int width = this.Parent == null ? this.Width : this.Parent.Width;

            Size sz = new Size(this.Width, Int32.MaxValue);
            sz = TextRenderer.MeasureText(this.Text, this.Font, sz, TextFormatFlags.WordBreak);
            this.Height = sz.Height + Padding.Bottom + Padding.Top;
        } finally {
            mGrowing = false;
        }
    }
    protected override void OnTextChanged(EventArgs e) {
        base.OnTextChanged(e);
        resizeLabel();
    }
    protected override void OnFontChanged(EventArgs e) {
        base.OnFontChanged(e);
        resizeLabel();
    }
    protected override void OnSizeChanged(EventArgs e) {
        base.OnSizeChanged(e);
        resizeLabel();
    }
}

int width = this.Parent == null ? this.Width : this.Parent.Width; pozwala to na użycie etykiety automatycznego wzrostu po zadokowaniu do elementu nadrzędnego, np. panelu.

this.Height = sz.Height + Padding.Bottom + Padding.Top; tutaj dbamy o wypełnienie u góry iu dołu.


1
  1. Umieść etykietę w panelu
  2. Chwyć ClientSizeChanged eventpanel, sprawiając, że etykieta wypełni przestrzeń:

    private void Panel2_ClientSizeChanged(object sender, EventArgs e)
    {
        label1.MaximumSize = new Size((sender as Control).ClientSize.Width - label1.Left, 10000);
    }
  3. Zestaw Auto-Sizeetykietę natrue

  4. Ustaw Docketykietę naFill

Czy kroki 3 i 4 zostały wykonane przez projektanta? Z jakichś powodów są to kroki 3 i 4?
Stealth Rabbi,

Są one wykonywane w projektancie (ale mogą być wykonane w kodzie, jeśli jest to potrzebne) i nie ma powodu do zamówienia.
noelicus

1

Nie jestem pewien, czy będzie pasować do wszystkich przypadków użycia, ale często używam prostej sztuczki, aby uzyskać zachowanie owijania: włóż Labeldo AutoSize=falseśrodka 1x1, TableLayoutPanelktóry zadba o Labelrozmiar.


1

Ustaw właściwość AutoEllipsis na „PRAWDA”, a właściwość AutoSize na „FALSE”.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj


0

Jeśli panel ogranicza szerokość etykiety, możesz ustawić właściwość Anchor etykiety na Left, Right i ustawić AutoSize na true. Jest to koncepcyjnie podobne do nasłuchiwania SizeChangedzdarzenia panelu i zaktualizowania MaximumSize etykiety do wartości new Size(((Control)sender).Size.Width, 0)sugerowanej w poprzedniej odpowiedzi . Każda strona wymieniona we właściwości Anchor jest, no cóż, zakotwiczona do odpowiedniej wewnętrznej strony zawierającej Kontroli. Zatem umieszczenie dwóch przeciwnych stron w zakotwiczeniu skutecznie określa wymiar formantu. Zakotwiczenie w lewo i prawo ustawia właściwość Szerokość elementu sterującego, a zakotwiczenie w górę i w dół ustawiłoby właściwość Wysokość.

To rozwiązanie, jako C #:

label.Anchor = AnchorStyles.Left | AnchorStyles.Right;
label.AutoSize = true;

Nie działa Etykieta zwiększa szerokość mojego panelu po prostu, że nie musi się zawijać. Niestety okno nie jest tak szerokie.
ygoe

0

Jeśli naprawdę chcesz ustawić szerokość etykiety niezależnie od treści, uważam, że najłatwiejszym sposobem jest:

  • Ustaw autosize true
  • Ustaw maksymalną szerokość, jak chcesz
  • Identycznie ustaw minimalną szerokość

Teraz etykieta ma stałą szerokość, ale automatycznie dostosowuje swoją wysokość.

Następnie w przypadku tekstu dynamicznego zmniejsz rozmiar czcionki. W razie potrzeby użyj tego fragmentu kodu w obszarze podrzędnym, w którym ustawiony jest tekst etykiety:

If Me.Size.Height - (Label12.Location.Y + Label12.Height) < 20 Then
    Dim naam As String = Label12.Font.Name
    Dim size As Single = Label12.Font.SizeInPoints - 1
    Label12.Font = New Font(naam, size)
End If

0

Pomogło mi to w moim formularzu o nazwie InpitWindow: In Designer for Label:

AutoSize = true;
Achors = Top, Left, Right.

private void InputWindow_Shown(object sender, EventArgs e) {
    lbCaption.MaximumSize = new Size(this.ClientSize.Width - btOK.Width - btOK.Margin.Left - btOK.Margin.Right -
        lbCaption.Margin.Right - lbCaption.Margin.Left, 
        Screen.GetWorkingArea(this).Height / 2);
    this.Height = this.Height + (lbCaption.Height - btOK.Height - btCancel.Height);
    //Uncomment this line to prevent form height chage to values lower than initial height
    //this.MinimumSize = new Size(this.MinimumSize.Width, this.Height);
}
//Use this handler if you want your label change it size according to form clientsize.
private void InputWindow_ClientSizeChanged(object sender, EventArgs e) {
    lbCaption.MaximumSize = new Size(this.ClientSize.Width - btOK.Width - btOK.Margin.Left * 2 - btOK.Margin.Right * 2 -
        lbCaption.Margin.Right * 2 - lbCaption.Margin.Left * 2,
        Screen.GetWorkingArea(this).Height / 2);
}

Cały kod mojej formy


0

Jeśli wymiary przycisku muszą pozostać niezmienione:

myButton.Text = "word\r\nwrapped"

0

Prostą odpowiedzią na ten problem jest zmiana właściwości DOCK etykiety. Domyślnie jest to „BRAK”.


0

Jeśli wcześniej wpisujesz tekst do etykiety, możesz to zrobić.

  1. W projektancie kliknij prawym przyciskiem myszy etykietę i wybierz Właściwości.
  2. W oknie Właściwości wyszukaj kartę tekstową.
  3. Kliknij kartę i kliknij przycisk strzałki obok niej.
  4. Na górze pojawi się okno.
  5. Możesz nacisnąć Enter w wyskakującym oknie, aby dodać linie i wpisać jak w notatniku! (NACISNĄĆ WPROWADŹ, GDZIE CHCESZ OWIJĄĆ TEKST ETYKIETY)

-12

Użyj style="overflow:Scroll"w etykiecie jak w poniższym HTML. Spowoduje to dodanie paska przewijania do etykiety w panelu.

<asp:Label
    ID="txtAOI"
    runat="server"
    style="overflow:Scroll"
    CssClass="areatext"
    BackColor="White"
    BorderColor="Gray"
    BorderWidth="1"
    Width = "900" ></asp:Label>

3
Głosowanie w tej sprawie jest w porządku, ale przynajmniej powiedz, dlaczego to zrobiłeś. Powodem tego było odrzucenie, ponieważ <asp: Label> nie jest używane w WinForms. Ta odpowiedź dotyczy niewłaściwej platformy.
theJerm

4
ponieważ jest to asp.net, a nie winform
Trikaldarshi,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.