Автоматическое управление текстовым полем по вертикали

В форме С# у меня есть панель, привязанная всеми сторонами, а внутри - текстовое поле, закрепленное сверху/влево/вправо.

Когда текст загружается в текстовое поле, я хочу, чтобы он автоматически расширялся по вертикали, так что мне не нужно прокручивать текстовое поле (прокрутите панель максимум, если текст больше не подходит для панели), есть ли способ сделать это с помощью текстового поля? (я не должен использовать этот элемент управления, поэтому, если есть другой элемент управления, который соответствует описанию, не стесняйтесь упоминать его)

Ответы

Ответ 1

Я предполагаю, что это многострочное текстовое поле, и вы позволяете ему расти вертикально. Этот код работал хорошо:

    private void textBox1_TextChanged(object sender, EventArgs e) {
        Size sz = new Size(textBox1.ClientSize.Width, int.MaxValue);
        TextFormatFlags flags = TextFormatFlags.WordBreak;
        int padding = 3;
        int borders = textBox1.Height - textBox1.ClientSize.Height;
        sz = TextRenderer.MeasureText(textBox1.Text, textBox1.Font, sz, flags);
        int h = sz.Height + borders + padding;
        if (textBox1.Top + h > this.ClientSize.Height - 10) {
            h = this.ClientSize.Height - 10 - textBox1.Top;
        }
        textBox1.Height = h;
    }

Вы должны сделать что-то разумное, когда текстовое поле пуст, например установка свойства MinimumSize.

Ответ 2

Текущий выбранный ответ НЕ обрабатывает строки без пробелов, таких как "jjjjjjjjjjjjjjjjjjj" x1000 (подумайте, что произойдет, если кто-то вставил URL-адрес)

Этот код решает эту проблему:

private void txtBody_TextChanged(object sender, EventArgs e)
{
    // amount of padding to add
    const int padding = 3;
    // get number of lines (first line is 0, so add 1)
    int numLines = this.txtBody.GetLineFromCharIndex(this.txtBody.TextLength) + 1;
    // get border thickness
    int border = this.txtBody.Height - this.txtBody.ClientSize.Height;
    // set height (height of one line * number of lines + spacing)
    this.txtBody.Height = this.txtBody.Font.Height * numLines + padding + border;
}

Ответ 3

Вы можете использовать Label и установить AutoSize на true.

Ответ 4

Я бы предложил использовать Graphics.MeasureString.

Сначала вы создаете объект Graphics, затем вызываете MeasureString на нем, передавая строку и шрифт текстового поля.

Пример

string text = "TestingTesting\nTestingTesting\nTestingTesting\nTestingTesting\n";

// Create the graphics object.
using (Graphics g = textBox.CreateGraphics()) {        
    // Set the control size to the string size.
    textBox.Size = g.MeasureString(text, textBox.Font).ToSize(); 
    textBox.Text = text;
}

Вы также можете ограничить его вертикальной осью, установив только свойство textBox.Size.Height и используя перегрузку MeasureString, которая также принимает int width.

Edit

Как отметил Слэкс, другой вариант использует TextRenderer.MeasureString. Таким образом, нет необходимости создавать объект Graphics.

textBox.Size = TextRenderer.MeasureString(text, textBox.Font).ToSize(); 

Здесь вы можете ограничить вертикальное изменение размера с помощью техники Ганса, передав дополнительный параметр Size на MeasureString с высотой int.MaxValue.

Ответ 5

Вы можете привязать его к нижней части, чтобы обеспечить изменение размера текстового поля по вертикали, когда изменяется форма, к которой она принадлежит. Кроме того, текстовое поле, которое меняет свой размер, может быть не изящным, поскольку оно может нарушить способ отображения других компонентов. Почему бы вам не указать максимальный размер, а не изменить его размер?

Ответ 6

Попробуйте этот подход:

код aspx.cs

protected int GetRows(object value) {
        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
            return 1;

        var contentTrimmed = value.ToString().Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ').Trim();

        var length = (decimal)contentTrimmed.Length;
        if (length == 0)
            return 1;

        int res = 0;
        decimal maxLength = 56;
        using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1)))
        {
             SizeF sizeRef = graphics.MeasureString("W", new Font("Segoe UI", 13, FontStyle.Regular, GraphicsUnit.Pixel));
             maxLength = maxLength * (decimal)sizeRef.Width;

             SizeF size = graphics.MeasureString(contentTrimmed, new Font("Segoe UI", 13, FontStyle.Regular, GraphicsUnit.Pixel));
             length = (decimal)size.Width;
        }

        res = (int)Math.Round(length / (decimal)maxLength, MidpointRounding.AwayFromZero);
        if (res == 0)
            return 1;

        return res;
 }

код aspx

<asp:TextBox ID="txtValue" TextMode="MultiLine" Text='<%# Eval("Value") %>' runat="server" MaxLength="500" Width="700px" Rows='<%# GetRows(Eval ("Value")) %>' ></asp:TextBox>