Ashish Agrawal Ashish Agrawal - 4 months ago 61
C# Question

UWP: Trimming the text of a TextBlock based on number of lines

I have an UWP application where I want to trim the text of the

TextBlock
if it goes beyond the third line and show "show more" link (tappable) in the end of the 3rd line.

I know to restrict number of lines I can use
MaxLines
property but it simply ignores the rest of the lines as if they don't exist. But I want to let the user know that there is some more text and he can tap on the show more link to navigate to the full text.

How can I achieve it?

Answer

Read the good topic which describes all step to create an expandable textblock

Also, view the source code on github

Here is the XAML code:

 <Grid x:Name="LayoutRoot" Tapped="LayoutRoot_OnTap">
     <Grid.RowDefinitions>
          <RowDefinition Height = "Auto" />
          <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <TextBlock Grid.Row="0" 
                  x:Name= "CommentTextBlock"
                  HorizontalAlignment= "Left"
                  TextWrapping= "Wrap"
                  Height= "Auto"
                  Width= "280" />

      < StackPanel Grid.Row= "1"
                  Orientation= "Horizontal"
                  HorizontalAlignment= "Right"
                  x:Name= "ExpandHint"
                  Visibility= "Collapsed"
                  Margin= "0,5,0,0" >
          < TextBlock  Text= "View More" />
           < TextBlock Margin= "10,0,10,0"
        Text= "+" />
      </ StackPanel >
</ Grid >

Here is C# part

public sealed partial class ExpandableTextBlock : UserControl
{
   public ExpandableTextBlock()
    {
        this.InitializeComponent();
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text", typeof(string), typeof(ExpandableTextBlock), new PropertyMetadata(default(string), OnTextChanged));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (ExpandableTextBlock)d;
        ctl.CommentTextBlock.SetValue(TextBlock.TextProperty, (string)e.NewValue);
        ctl.CommentTextBlock.SetValue(TextBlock.HeightProperty, Double.NaN);

        ctl.CommentTextBlock.Measure(new Size(ctl.CommentTextBlock.Width, double.MaxValue));

        double desiredheight = ctl.CommentTextBlock.DesiredSize.Height;
        ctl.CommentTextBlock.SetValue(TextBlock.HeightProperty, (double)63);

        if (desiredheight > (double)ctl.CommentTextBlock.GetValue(TextBlock.HeightProperty))
        {
            ctl.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Visible);
            ctl.MaxHeight = desiredheight;
        }
        else
        {
            ctl.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Collapsed);
        }

        //Setting length of comments
        var boundsWidth = Window.Current.Bounds.Width;
        ctl.CommentTextBlock.SetValue(TextBlock.WidthProperty, boundsWidth);
    }

    public static readonly DependencyProperty CollapsedHeightProperty = DependencyProperty.Register(
        "CollapsedHeight", typeof(double), typeof(ExpandableTextBlock), new PropertyMetadata(default(double), OnCollapsedHeightChanged));


    public double CollapsedHeight
    {
        get { return (double)GetValue(CollapsedHeightProperty); }
        set { SetValue(CollapsedHeightProperty, value); }
    }

    private static void OnCollapsedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (ExpandableTextBlock)d;
        ctl.CollapsedHeight = (double)e.NewValue;
    }


    public static readonly DependencyProperty TextStyleProperty = DependencyProperty.Register(
       "TextStyle", typeof(Style), typeof(ExpandableTextBlock), new PropertyMetadata(default(Style), OnTextStyleChanged));

    public Style TextStyle
    {
        get { return (Style)GetValue(TextStyleProperty); }
        set { SetValue(TextStyleProperty, value); }
    }

    private static void OnTextStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (ExpandableTextBlock)d;
        ctl.CommentTextBlock.SetValue(StyleProperty, (Style)e.NewValue);
    }

    private void LayoutRoot_OnTap(object sender, TappedRoutedEventArgs tappedRoutedEventArgs)
    {
       if ((Visibility)this.ExpandHint.GetValue(StackPanel.VisibilityProperty) == Visibility.Visible)
        {
            //transition
            this.CommentTextBlock.SetValue(TextBlock.HeightProperty, Double.NaN);

            this.ExpandHint.SetValue(StackPanel.VisibilityProperty, Visibility.Collapsed);
        }
    }
}