web-dev-qa-db-ja.com

テキストボックスコントロールを垂直方向に自動サイズ変更

C#フォームでは、パネルがすべての側面に固定され、内部にテキストボックスが上/左/右に固定されています。

テキストがテキストボックスに読み込まれると、テキストボックスをスクロールする必要がないように、テキストが垂直方向に自動的に展開されるようにします(パネルに収まらないテキストが他にもある場合は、最大でもパネルをスクロールします)。テキストボックスでこれを行う方法はありますか? (私はこのコントロールを使用するように制約されていないので、説明に合う別のコントロールがある場合は、それについて自由に言及してください)

16
Andrei S

これは複数行のテキストボックスであり、垂直方向に拡大できると想定します。このコードはうまく機能しました:

    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;
    }

最小サイズプロパティの設定など、テキストボックスが空の場合は、適切な処理を行う必要があります。

25
Hans Passant

現在選択されている回答は、「jjjjjjjjjjjjjjjjjjjj」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;
}
30
David Sherret

ラベルを使用して、AutoSizeをtrueに設定できます。

2
SLaks

Graphics.MeasureString を使用することをお勧めします。

最初にGraphicsオブジェクトを作成し、次にそのオブジェクトでMeasureStringを呼び出して、文字列とテキストボックスのフォントを渡します。

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

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

textBox.Size.Heightプロパティのみを設定し、int widthも受け入れるMeasureStringオーバーロードを使用して、垂直軸に制限することもできます。

編集

SLaksが指摘したように、別のオプションは TextRenderer.MeasureString を使用することです。この方法では、Graphicsオブジェクトを作成する必要はありません。

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

ここでは、ハンスの手法を使用して垂直方向のサイズ変更に制限し、追加のSizeパラメーターをint.MaxValueの高さでMeasureStringに渡すことができます。

2
GeReV

下部に固定すると、テキストボックスが属するフォームのサイズが変更されるたびに、テキストボックスのサイズが垂直方向に変更されます。また、サイズを変更するテキストボックスは、他のコンポーネントの表示方法を混乱させる可能性があるため、エレガントなものではない可能性があります。サイズを変更するのではなく、最大サイズを指定してみませんか?

0
npinti

このアプローチを試してください:

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>
0