Tuesday, February 15, 2011

WPF: Textblock vertical alignment with given height

I was needed to set the alignment of textblock in center and also need to set height which is greater than normal textblock text height. But problem is when the text height is assigned then vertical alignment of textblock does not work. To solve this problem easy way to set padding so that the textblock text remain at center position. For that you need to measure the height of textblock before setting the custom height of textblock. After getting the desiredsize of textblock you can calculate the top padding of text in textblock. Then set the padding and custom height of textblock. This will solve the problem of making text position at center giving custom height.
textBlock.Measure(new Size(infiniteWidth, infiniteHeight));
var textBlockHeight = textBlock.DesiredSize.Height;
var textBlockTopPaddig = (CustomHeight - textBlockHeight)/2;
textBlock.Padding = new Thickness(0,textBlockTopPaddig,0,0);
textBlock.Height = CustomHeight;
 
XAML 
But if you want to set the custom height of TextBox from XAML then create a StackPanel and set the TextBlock inside that StackPanel. Instead of setting TextBlock height set the height of StackPanel and set StackPanel vertical alignment as VerticalAlignment.Center. So now textblock will be displayed in center of StackPanel. 

Friday, February 11, 2011

WPF : Getting Size of Text of a TextBlock or Richtext from code-behind without Rendering

We can not get actual size of a textblock without rendering. So for getting the size of TextBlock or RichText we need to call measure function of TextBlock / Richtext to get the the width and height which it would desired to occupy when it will render and you will get this from DesiredSize property after calling measure function.
TextBlock textBlock = new TextBlock();
textBlock.TextWrapping = TextWrapping.Wrap;
textBlock.Text = “Test data”;
textBlock.Measure(new Size(400, 500));
there the measure takes the size which is available size of container element. We can give it infinity size for measuring the size of text.
There also have another low-level .NET class for measuring the size of Text without creating TextBlock.And it is FormattedText class. Actually TextBlock internally use FormattedText for measuring the size of Text. For measuring text size we can create object of FormattedText like this.
string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
                       // Create the initial formatted text string.
                       FormattedText formattedText = new FormattedText(
                           testString,
                           CultureInfo.GetCultureInfo("en-us"),
                           FlowDirection.LeftToRight,
                           new Typeface("Verdana"),
                           32,
                           Brushes.Black);
Here we have defined an object of FormattedText class which actually takes text as string, cultureinfo, direction, font type , size of text and media brush.
This return the same size as Measure function of text block.
But we can not measure the Rich text using FormattedText function as format of every Run (Paragraph) is different. So for that we need to extract the direction, font , size of text and brush for every run element. There have a nice article for getting FormattedText from FlowDocument of RichText object. http://www.wpfmentor.com/2009/01/how-to-transfer-rich-text-from.html.