Silverlight 4 added TextTrimming=”WordEllipsis”, which trims the text that a TextBlock displays based on the available width. This blog post describes a simple method for automatically showing the full text as a tooltip whenever the text is trimmed. This is presented as an attached behaviour.
UPDATE: I have updated this solution to support both WPF and Silverlight, see my recent blog post.
The TextTrimming feature of SL4 allows us to worry a little less about the layout of our applications, giving the option to use fixed widths when rendering text. This can be particularly useful if you have to localize your application. However, arbitrarily trimming the text without providing the user with a mechanism to see the full text is not great for the user. A simple solution is to use a tooltip to present the full text.
Detecting whether the a TextBlock’s text is being trimmed is not something that is available from the TextBlock’s API, there is no IsTrimmed property! A quick search of the Silverlight forums drew a dead end. I did find a decent WPF solution, however this uses various parts of the WPF API that are not present in Silverlight.
Eventually I found that there is a very simple solution … quoting from the MSDN page on Text and Fonts:
You can detect clipped text programmatically because ActualWidth for a TextBlock always reports the expanded size of the text, even if it does not fit in the layout container. If you know where to read the Width for the layout container that is doing the clipping, you can compare these two values.
Therefore, if a TextBlock is trimming the text, the reported ActualWidth of the TextBlock will be the width that the TextBlock requires to render the text in its entirety, not the actual width of the rendered text!

In the example above, the Width of the TextBlock is set explicity, however it is more common that the width of TextBlock is determined by its parent container, a Grid for example.
To wrap this functionality up into something re-useable, I have created a AutoToolTip attached behaviour. The code for this is shown below:
public class TextBlockUtils { /// <summary> /// Gets the value of the AutoTooltipProperty dependency property /// </summary> public static bool GetAutoTooltip(DependencyObject obj) { return (bool)obj.GetValue(AutoTooltipProperty); } /// <summary> /// Sets the value of the AutoTooltipProperty dependency property /// </summary> public static void SetAutoTooltip(DependencyObject obj, bool value) { obj.SetValue(AutoTooltipProperty, value); } /// <summary> /// Identified the attached AutoTooltip property. When true, this will set the /// TextBlock TextTrimming property to WordEllipsis, and display a tooltip with /// the full text whenever the text is trimmed. /// </summary> public static readonly DependencyProperty AutoTooltipProperty = DependencyProperty.RegisterAttached("AutoTooltip", typeof(bool), typeof(TextBlockUtils), new PropertyMetadata(false, OnAutoTooltipPropertyChanged)); private static void OnAutoTooltipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock textBlock = d as TextBlock; if (textBlock == null) return; if (e.NewValue.Equals(true)) { textBlock.TextTrimming = TextTrimming.WordEllipsis; ComputeAutoTooltip(textBlock); textBlock.SizeChanged += TextBlock_SizeChanged; } else { textBlock.SizeChanged -= TextBlock_SizeChanged; } } private static void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e) { TextBlock textBlock = sender as TextBlock; ComputeAutoTooltip(textBlock); } /// <summary> /// Assigns the ToolTip for the given TextBlock based on whether the text is trimmed /// </summary> private static void ComputeAutoTooltip(TextBlock textBlock) { FrameworkElement parentElement = VisualTreeHelper.GetParent(textBlock) as FrameworkElement; if (parentElement != null) { if (textBlock.ActualWidth > parentElement.ActualWidth) { ToolTipService.SetToolTip(textBlock, textBlock.Text); } else { ToolTipService.SetToolTip(textBlock, null); } } } } |
Most of this is boiler-plate attached behaviour code. The most interesting method is ComputeAutoTooltip which determines whether a tooltip is required. This simply looks at the ActualWidth of the parent and compares it to the ActualWidth of the TextBlock.
To use this code, ensure that your TextBlock is placed within its own Grid, then set the attached property to true. You can see this in action below:
<Grid util:GridUtils.ColumnDefinitions="2*," util:GridUtils.RowDefinitions=","> <sdk:GridSplitter Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" ShowsPreview="True" Background="LightGray" Width="10" HorizontalAlignment="Right"/> <Grid Grid.Column="0" Margin="0,0,10,0"> <TextBlock Text="The rain in Spain stays mainly in the plain" util:TextBlockUtils.AutoTooltip="True"/> </Grid> <Grid Grid.Column="2"> <TextBlock Text="In Hertford, Hereford, and Hampshire, hurricanes hardly ever happen" util:TextBlockUtils.AutoTooltip="True"/> </Grid> <Grid Grid.Column="0" Grid.Row="1" Margin="0,0,10,0"> <TextBlock Text="Peter Piper picked a peck of pickled peppers" util:TextBlockUtils.AutoTooltip="True"/> </Grid> <Grid Grid.Column="2" Grid.Row="1"> <TextBlock Text="She sells sea-shells on the sea-shore" util:TextBlockUtils.AutoTooltip="True"/> </Grid> </Grid> |
Note the use of the simplified grid syntax which I blogged about earlier. You can see this code in action below. Move the grid splitter to see the tooltips automatically enabled when an ellipsis is displayed:
You can download the full sourcecode here: AutoTooltipTextBlock.zip
Regards, Colin E.
Tags: attached behaviour, ellipsis, textblock


email: ceberhardt@scottlogic.co.uk
on Google+



Thanks for post.
I tried to apply the code using datagrid but It doesn’t work correctly. When I resize the data grid column, the dataGrid doesn’t fire the event SizeChanged from the textblock but It happens if the texbox is trimmed so the tooltip never appear.
Another point is:
I get bug when I use this line:
ToolTipService.SetToolTip(textBlock, null);
My solution was:
We should not set the tooltip null It would be good to get use:
var toolTip= ToolTipService.GetToolTip(textBlock);
If you want to hide you just use:
toolTip.Visibility = Visibility.Collapsed;
If the textblock has a existing toolTip just change the message and make it visible again:
toolTip.Content = textBlock.Text;
toolTip.Visibility = Visibility.Visible;
Please if you know any work around about the resizing stuff send me an e-mail.
Thanks guys
A while ago i solved a similar problem using silverlight 3. see link below.
It has word ellipses and ability to show htmls links, bold, italics etc.
Nevertheless, Thanks for submitting this one. I almost missed it in silverlight 4!!!
http://subodhnpushpak.wordpress.com/2010/02/02/html-text-in-silverlight-controls-with-ellipses-tooltip-and-rollover/
[...] Automatically Showing ToolTips on a Trimmed TextBlock (Colin Eberhardt) [...]
I’ve tried the WPF code you linked to, and it doesn’t work well — for example, if you databind the FontWeight, it still uses the original font weight to decide whether the tooltip should be shown.
Your method is elegant and simple… unfortunately it doesn’t work in WPF, only Silverlight. In WPF, Width is NaN since I never explicitly assigned a width, ActualWidth is the width assigned by the container (which evidently is what Width is used for in Silverlight), and there isn’t a property giving the width of the full text. Rats!
Hi Joe, I hadn’t spotted those issues in the WPF solution I linked to. I have posted my own WPF solution here:
http://www.scottlogic.co.uk/blog/colin/2011/01/automatically-showing-tooltips-on-a-trimmed-textblock-silverlight-wpf/
thats so easy! thanks for sharing
Automatically Showing ToolTips on a Trimmed TextBlock (Silverlight) | Colin Eberhardt’s Adventures in WPF…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
Thanks,It looks things are very easy.