Silverlight : How to predict string size?
I'm facing a lot of problem with Silverlight way to deal with layout. Mainly, I can't find a way to predict the size occupied by strings before they are actually drawn. On iPhone, we have some very simple methods that allow us to determine the size a string will occupy on screen based on font size, word wrapping option and available width and/or height. But with Silverlight, I can't find a way to have consistent results across my app.
I'm currently using the ActuelHeight and ActualWidth of a TextBlock instance but it gives me random results. For instance, I a use the following code...
TextBlock proto = new TextBlock();
proto.Width = 456;
proto.TextWrapping = TextWrapping.Wrap;
proto.Text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
double h = proto.ActualHeight;
...h is set to 66 pixels ! As you can guess by yourself, there is no way such a long text could fit on a rectangle of 456 pixels wide and开发者_运维百科 66 pixels high. And it is confirmed when I add the text block inside a canvas, set its size to {456;66} and test the app : the text doesn't fit on the text block at all !
Can someone explain me where the problem lies and point me to a consistent (and trustable) way to measure string sizes ?
Thanks by advance,
Eric.
You can ask the TextBlock
to measure itself (without it yet being displayed) by calling its Measure
method:
textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var width = textBlock.DesiredSize.Width;
var height = textBlock.DesiredSize.Height;
Of course, it may not have infinite width and height, so depending on your use case you may prefer to ask your root element to measure itself, which will in turn measure all children (including the TextBlock
).
Where possible, try and create a design where you don't need to know the physical size of a textblock. Use a scrolling design and dynamic resizing to avoid needing to know this.
However, if you really must know this, you could try this trick from the desktop (where it wasn't possible to use MeasureText - sorry not supported in Silverlight). Add the textblock to the UI but out of the visible area or behind another control. You could then get the actual rendered size.
The TextBlock won't Resize until it is actually shown...
For the rest I think this is a matter of design. In a XAML environment you shouldn't have to know/set pixelsizes very often.
Thanks for your help guys, actually my first method was working ! But I forgot to set the fontSize before retrieving ActualHeight - and it was set automatically by the parent once added to the visual tree ! So 66 pixels was actually the right height of my text block with the small font size used by default by the text block. Once added to the visual tree, the font size of the text block was way bigger, leading to cliping.
Again, thanks for your help !
My solution is to use 3 or more TextBlocks:
string[] dataSeparator = new string[] { "\n" };
string[] data;
data = longString.Split(dataSeparator, StringSplitOptions.None);
TB1.Text = string.Empty;
TB2.Text = string.Empty;
TB3.Text = string.Empty;
int length = data.Length / 3;
for (int i = 0; i < length; i++)
{
TB1.Text += data[i] + "\n";
}
for (int i = length; i < length * 2; i++)
{
TB2.Text += data[i] + "\n";
}
for (int i = length * 2; i < data.Length; i++)
{
TB3.Text += data[i] + "\n";
}
精彩评论