可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In a C# form, I have a panel anchored all sides, and inside, a textbox, anchored top/left/right.
When text gets loaded into the textbox, i want it to auto expand itself vertically so that I don't need to scroll the textbox (scroll the panel at most, if there is more text that doesn't fit the panel).
is there any way to do this with a textbox? (i'm not constrained to use this control so if there's another control that fits the description, feel free to mention it)
回答1:
I'll assume this is a multi-line text box and that you'll allow it to grow vertically. This code worked well:
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;
}
You ought to do something reasonable when the text box is empty, like setting the MinimumSize property.
回答2:
The current selected answer does NOT handle lines with no spaces such as "jjjjjjjjjjjjjjjjjjjj"x1000 (think about what would happen if someone pasted a URL)
This code solves that problem:
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:
You can use a Label, and set AutoSize to true
.
回答4:
I'd suggest using Graphics.MeasureString
.
First you create a Graphics
object, then call MeasureString
on it, passing the string and the textbox's font.
Example
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;
}
You could also limit it to the vertical axis by setting only the textBox.Size.Height
property and using the MeasureString
overload which also accepts int width
.
Edit
As SLaks pointed out, another option is using TextRenderer.MeasureString
. This way there's no need to create a Graphics
object.
textBox.Size = TextRenderer.MeasureString(text, textBox.Font).ToSize();
Here you could limit to vertical resizing using Hans' technique, passing an extra Size
parameter to MeasureString
with int.MaxValue
height.
回答5:
You could anchor it to the bottom, that will ensure that the textbox is resized vertically when ever the form to which it belongs is resized.
Also, a textbox that changes its size might not be an elegant thing since it might disrupt the way that other components are displayed. Why don't you give it a maximum size instead of having it resized?
回答6:
Try this approach:
aspx.cs code
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 code
<asp:TextBox ID="txtValue" TextMode="MultiLine" Text='<%# Eval("Value") %>' runat="server" MaxLength="500" Width="700px" Rows='<%# GetRows(Eval ("Value")) %>' ></asp:TextBox>