I have an GridItem that has a fixed Height/Width.
It contains a textblock that has the max line set.
How can I determine if this text is trimmed? I want to add special functionality if it is trimmed.
Old Way - when TextWrapping is set to None
To know if a TextBlock
is trimmed, we can subscribe to its SizeChanged
event and compare its ActualWidth
to the MaxWidth
you specified. To get the right ActualWidth
of the TextBlock
, we will need to leave the TextTrimming
to its default value (i.e. TextTrimming.None
), and set it to trimmed once the width goes over.
New Way - when TextWrapping is set to Wrap
Now that I know because the TextWrapping
is set to Wrap
and assume the VirticalAlignment
is not specified (default to Stretch
), the Width
will always stay the same. We only need to monitor the SizeChanged
event when the actual height of the TextBlock
exceeds the height of its parent.
Let's use a Behavior
to encapsulate all the logic above. What needs to be mentioned here is that a static
helper class with a bunch of attached properties or a new control that inherits from TextBlock
can do exactly the same thing; but being a big Blend fan, I prefer to use Behaviors
whenever possible.
The Behavior
public class TextBlockAutoTrimBehavior : DependencyObject, IBehavior
{
public bool IsTrimmed
{
get { return (bool)GetValue(IsTrimmedProperty); }
set { SetValue(IsTrimmedProperty, value); }
}
public static readonly DependencyProperty IsTrimmedProperty =
DependencyProperty.Register("IsTrimmed", typeof(bool), typeof(TextBlockAutoTrimBehavior), new PropertyMetadata(false));
public DependencyObject AssociatedObject { get; set; }
public void Attach(DependencyObject associatedObject)
{
this.AssociatedObject = associatedObject;
var textBlock = (TextBlock)this.AssociatedObject;
// subscribe to the SizeChanged event so we will know when the Width of the TextBlock goes over the MaxWidth
textBlock.SizeChanged += TextBlock_SizeChanged;
}
private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
// ignore the first time height change
if (e.PreviousSize.Height != 0)
{
var textBlock = (TextBlock)sender;
// notify the IsTrimmed dp so your viewmodel property will be notified via data binding
this.IsTrimmed = true;
// unsubscribe the event as we don't need it anymore
textBlock.SizeChanged -= TextBlock_SizeChanged;
// then we trim the TextBlock
textBlock.TextTrimming = TextTrimming.WordEllipsis;
}
}
public void Detach()
{
var textBlock = (TextBlock)this.AssociatedObject;
textBlock.SizeChanged += TextBlock_SizeChanged;
}
}
The XAML
<Grid HorizontalAlignment="Center" Height="73" VerticalAlignment="Center" Width="200" Background="#FFD2A6A6" Margin="628,329,538,366">
<TextBlock x:Name="MyTextBlock" TextWrapping="Wrap" Text="test" FontSize="29.333">
<Interactivity:Interaction.Behaviors>
<local:TextBlockAutoTrimBehavior IsTrimmed="{Binding IsTrimmedInVm}" />
</Interactivity:Interaction.Behaviors>
</TextBlock>
</Grid>
Note that the Behavior
exposes a dependency property IsTrimmed
, you can data bind it to a property in your viewmodel (i.e. IsTrimmedInVm
in this case).
P.S. There's no FormattedText
function in WinRT otherwise the implementation could be a little bit different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With