How to find how much text fits in a textbox without scrolling - c#

I have a relatively large text. I need to add a certain amount of this text to a textbox so that it can be visible without scrolling , then add the rest of the text to another textbox and then another -.-.-.> looping through the text generating as many textboxes as necessary.
My problem is i don't know how to find out how much of the text fits in each textbox. So far the only thing i was able to do is assign a fixed number of characters that fit in a page. But this would not do for different screen resolutions. Is there a way, a trick or a workaround i can use to calculate how much of a text can fit into a textbox with fixed font and fontsize but relative width and height?
int TextLength = 1000, PageStart = 0;
List<TextBox> Pages = new List<TextBox>();
while (PageStart < TextLength)
{
TextBox p = new TextBox();
if (PageStart + PageLength < TextLength)
{
p.PageText = Text.Substring(PageStart, PageLength);
PageStart += PageLength;
Pages.Add(p);
}
else
{
PageLength = TextLength - PageStart;
p.PageText = Text.Substring(PageStart, PageLength);
Pages.Add(p);
break;
}
}

You would probably be better of using a TextBlock. Other than that the TextBlock measuring technique should work for TextBoxes too - how to calculate the textbock height and width in on load if i create textblock from code?
You would need to measure ActualHeight while increasing the amount of text until you go over your limit.

Related

Calculate character capacity of a textbox with known Width and Height and Font in wpf

I am trying to calculate how many characters or Text can fit in a TextBox with Wrap.
And I want to remove the over flow text.
I am passing the string to a TextBox at runtime and I want to truncate the extra part of the string and display only the Substring which can easily fit into TextBox of dynamic width and Height and font.
User can specify any width and Height and any font.
Is there any way to calculate number of characters which can fit in the text box of given Height and Width in WPF?
I have Tried to achieve this like:
`
if (fontSize <=minimumFontSize &&
formattedText.WidthIncludingTrailingWhitespace > textBoxWidth)
{
do {
//reduce length;
length -= 1;
truncationText = formattedText.Text.Truncate(length);
formattedText= GetFormattedText(myTextBox, truncationText);
}
while (fontSize <=minimumFontSize && formattedText.WidthIncludingTrailingWhitespace > textBoxWidth)
`

Fix row height of every row in TableLayoutPanel

I'm working on Windows c#.
Firstly, the things those can not be change as my need are following:
The Size of TableLayoutPanel is fixed.
The Total # of columns are fixed.
Now, I want to set a fix height for all rows but as increasing the rows, if I set the RowStyle property to Percent with 100.0F then it works fine for 3 to 4 items, but after 4-5 items, the control on one row overwrites controls on another row.
I have searched for this so more but i'm not able to get the proper answer. I have also tried the AutoSize, Percent, Absolute properties of RowStyle, even though it is not working.
So what to do and how? How can I achieve this?
Ultimately, I want to do same like as DataGridView of Windows C#.
Thanks in advance....
I'm working on WinForms...the sample code is here..
int cnt = tableLayout.RowCount = myDataTable.Rows.Count;
tableLayout.Size = new System.Drawing.Size(555, 200);
for (int i = 1; i <= cnt; i++)
{
Label lblSrNo = new Label();
lblSrNo.Text = i.ToString();
TextBox txt = new TextBox();
txt.Text = "";
txt.Size = new System.Drawing.Size(69, 20);
tableLayout.Controls.Add(lblSrNo, 0, i - 1);
tableLayout.Controls.Add(txt, 1, i - 1);
}
tableLayout.RowStyles.Clear();
foreach (RowStyle rs in tableLayout.RowStyles)
tableLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
The label and textboxes are working fine for 4-5 #of rows but whenever the #of row(in this case, variable cnt in for loop) increases, the rows are overwriting each other that is one control overwrite to another...I had drag-drop the TableLayoutPanel control and created just one row and 2 columns manually.
So please tell me how to do it.
I'm still new to tableLayoutPanels myself, but I noticed that at the bottom of your code, you're Clearing all the rowstyles from the collection, then you're trying to iterate through them in your foreach loop.
You did this:
tableLayout.RowStyles.Clear(); //now you have zero rowstyles
foreach (RowStyle rs in tableLayout.RowStyles) //this will never execute
tableLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
Try this instead.
TableLayoutRowStyleCollection styles =
tableLayout.RowStyles;
foreach (RowStyle style in styles){
// Set the row height to 20 pixels.
style.SizeType = SizeType.Absolute;
style.Height = 20;
}
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Edit: I just realized that adding N rows doesn't add N rowstyles that you can iterate through. I think what's happening is that you're adding N rows, but none of them have a rowstyles.
I suppose you can Clear() the rowstyles, then just add N rowstyles similar to how you're already doing.
There are 2 ways to increase the row height of table layout panel.
Look into the following link :
https://social.msdn.microsoft.com/Forums/windows/en-US/d80db8e1-d6cc-48b8-957f-0f73263c6d4a/how-to-change-the-row-height-of-a-tablelayoutpanel-at-runtime?forum=winforms
It specifies by setting the YourTableLayoutPanel.RowStyles[index].Height int he code behind class.
The other way is to set the row height in the designer of your UI. Through UI, go into Rows properties of the panel, select the row and set the required height using percent or absolute

Listview items text is trucncated and doesn't show it all

I am usign a code a code like this and when the text gets long, it cuts it off and doesn't show the whole text :( In this aspect I want it to behave like a list box item. One line was for one item in the list box and didn't have this trucnacted text issue.
listView1.Scrollable = true;
listView1.View = View.Details;
listView1.HeaderStyle = ColumnHeaderStyle.None;
ColumnHeader header = new ColumnHeader();
header.Text = "MyHeader";
header.Name = "MyColumn1";
listView1.Columns.Add(header);
listView1.Items.Add("TooLongTextDoesntShow");
listView1.Items.Add("short");
listView1.Items.Add("abcd");
I think it is just easier to attach a picture of the issue. Please notice how it is not displaying full text of the highlighted item :(
Thanks for your help.
Just specify a column header width.
ColumnHeader header = new ColumnHeader();
header.Text = "MyHeader";
header.Name = "MyColumn1";
header.Width = listView1.Width //Same Width as Entire List Control
listView1.Columns.Add(header);
Alternative ways to do, is during the add.
You can make use of: ListView.ColumnHeaderCollection.Add
public virtual ColumnHeader Add(
string text,
int width //width of the header
)
Ok, I found a solution, please let me know if there are better ways of doing it too
AFTER adding items to list view is done, we should call this:
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
We take an example of ListView with 2 columns and resize on contents and then to minimum width.
// Auto resize of ListView Columns to minimum width
private int[] ColumnsWidth = { 35, 322 };
/// <summary>
/// Resize the columns based on the items entered
/// </summary>
private void ResizeColumns()
{
// Auto Resize Columns based on content
m_urlsListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
// Make sure to resize to minimum width
if (m_urlsListView.Columns[0].Width < ColumnsWidth[0])
{
m_urlsListView.Columns[0].Width = ColumnsWidth[0];
}
if (m_urlsListView.Columns[1].Width < ColumnsWidth[1])
{
m_urlsListView.Columns[1].Width = ColumnsWidth[1];
}
}
The content is being truncated because of (practically invisible) column. You can tell the ListView to adjust the column widths automatically:
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
You can just add a column and define its width according to your text size requirement. Moreover "Scrollable" property can be set to true if the actual width of the listview control is smaller
ListView_Column_Width_Image

How to AutoSize the height of a Label but not the width

I have a Panel that I'm creating programmatically; additionally I'm adding several components to it.
One of these components is a Label which will contain user-generated content.
I don't know how tall the label should be, but it does have a fixed width.
How can I set the height so that it displays all the text, without changing the width?
Just use the AutoSize property, set it back to True.
Set the MaximumSize property to, say, (60, 0) so it can't grow horizontally, only vertically.
Use Graphics.MeasureString:
public SizeF MeasureString(
string text,
Font font,
int width
)
The width parameter specifies the
maximum value of the width component
of the returned SizeF structure
(Width). If the width parameter is
less than the actual width of the
string, the returned Width component
is truncated to a value representing
the maximum number of characters that
will fit within the specified width.
To accommodate the entire string, the
returned Height component is adjusted
to a value that allows displaying the
string with character wrap.
In other words, this function can calculate the height of your string based on its width.
If you have a label and you want have control over the the vertical fit, you can do the following:
MyLabel.MaximumSize = new Size(MyLabel.Width, 0)
MyLabel.Height = MyLabel.PreferredHeight
MyLabel.MaximumSize = new Size(0, 0)
This is useful for example if you have a label in a container that can be resized. In that case, you can set the Anchor property so that the label is resized horizontally but not vertically, and in the resize event, you can fit the height using the method above.
To avoid the vertical fitting to be interpreted as a new resize event, you can use a boolean:
bool _inVerticalFit = false;
And in the resize event:
if (_inVerticalFit) return;
_inVerticalFit = true;
MyLabel.MaximumSize = new Size(MyLabel.Width, 0)
MyLabel.Height = MyLabel.PreferredHeight
MyLabel.MaximumSize = new Size(0, 0)
_inVerticalFit = false;

LinkLabel needing more space than TextRenderer.MeasureText says

If I give TextRenderer.MeasureText some text to measure and width to use it will return the height needed to display that text.
private static int CalculateHeight(string text, Font font, int width)
{
Size size = TextRenderer.MeasureText(text, font, new Size(width, Int32.MaxValue), TextFormatFlags.NoClipping | TextFormatFlags.WordBreak);
return size.Height;
}
If I give that text, width and height to a LinkLabel it would display the text in the width and height provided with nothing clipped off.
However, if I put a Link into the LinkLabel.Links collection, the LinkLabel will draw the text with what appears to be a little more spacing between the characters and at times this will cause the end of the text to be clipped. Is there anyway to prevent this? I've tried adding padding when there is a link, but there's no reliable way to know exactly how much more space will be needed. Are there any other ways to do this?
You should use Control.GetPreferredSize method to calculate width or height needed for control (LinkLabel in your case). You should not use MeasureText for such purposes, more detailed explanation you can find here (Accuracy of TextRenderer.MeasureText results.)
If a LinkLabel contains more than one link, or there are parts of text which are nor in a link, then the control uses Graphics.DrawString/MeasureString instead of TextRenderer.DrawText/MeasureText. You can easily see it in action, the biggest difference in rendering is with the small L letter:
linkLabel1.Text = new string('l', 100); // 100 x small L
linkLabel1.LinkArea = new LinkArea(0, 50);
linkLabel2.Text = new string('l', 100); // 100 x small L
TextRenderer.MeasureText is a managed wrapper for the DrawTextEx API. The value returned comes from the lprc struct. You might want to look at that API for more details.
I guess you could remove the style that makes it underline. linkLabel.Styles.Add("text-decoration", "none"); but then of course it wouldn't look like a link. :-/
Another solution would be to add the padding yourself I guess.
int heightBefore = linkLabel.Height;
int fontHeight = CalculateHeight(linkLabel.Text, linkLabel.Font, linkLabel.Width);
int paddingHeight = heightBefore - fontHeight;
linkLabel.Font = otherFont;
linkLabel.Height = CalculateHeight(linkLabel.Text, otherFont, linkLabel.Width);
linkLabel.Height += paddingHeight;
Not the prettiest of solutions, but I would guess it works.

Categories

Resources