When text wraps within TextBlock, ActualHeight is incorrect

1k Views Asked by At

I have a TextBlock with a Border around it that's inside of a Canvas that I'm using to animate it as part of a custom control. The block slides in from the bottom of the screen over the top of the image. I'm trying to use the ActualHeight of the TextBlock to determine how far to move it onto the page, but when there is so much text that it wraps to two lines, the ActualHeight returns the same size as though there was a single line.

TextBlock:

<DataTemplate DataType="{x:Type contentTypes:BusinessAdText}" x:Key="BusinessAdTextTemplate">
    <Border Background="#a9a9a975"
        Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualWidth}">
        <TextBlock Margin="20" Text="{Binding Text}"
            TextWrapping="Wrap">
        </TextBlock>
        </Border>
</DataTemplate>

This style is applied which has the canvas:

<Style TargetType="local:BusinessAd">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:BusinessAd">
                <Border Background="Transparent">

                    <Canvas ClipToBounds="True">
                        <ContentPresenter x:Name="PART_Content"                                                  
                                            VerticalAlignment="Center"
                                            HorizontalAlignment="Center" />
                    </Canvas>

                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Code behind for BusinessAd.cs has:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    _contentPart = GetTemplateChild("PART_Content") as FrameworkElement;                        
}

Then just using a simple DoubleAnimation I move it onto the screen:

if (_contentPart != null && _isLoaded)
{
    _storyboard.Stop();

    vAnimation.From = ActualHeight;
    vAnimation.To = ActualHeight - _contentPart.ActualHeight;
    //_contentPart.ActualHeight returns 46.something no matter how much text is there

    vAnimation.Duration = new Duration(TimeSpan.FromSeconds(Duration));

    if (_storyboard.Children.Count == 0)
    {
        _storyboard.Children.Add(vAnimation);

        Storyboard.SetTargetProperty(vAnimation, new PropertyPath("(Canvas.Top)"));
        Storyboard.SetTarget(vAnimation, _contentPart);                                                           
    }

    _storyboard.Begin();
}
2

There are 2 best solutions below

0
On

I'm not sure if this applies to you, but for me, the textblock in Windows.UI.Xaml.Controls needs to be preceded with this:

myTextBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

Before, when I had just myTextBlock.Measure(new Size());, it worked when there wasn't any text wrapping, but with wrapping ActualWidth and ActualHeight returned the dimensions of the word/letter, depending on WrapWholeWords or Wrap

1
On

You have to call UpdateLayout() before checking ActualHeight:

if (_contentPart != null && _isLoaded)
{
    _storyboard.Stop();
    UpdateLayout();

    vAnimation.From = ActualHeight;
    vAnimation.To = ActualHeight - _contentPart.ActualHeight;
    //_contentPart.ActualHeight returns 46.something no matter how much text is there

    vAnimation.Duration = new Duration(TimeSpan.FromSeconds(Duration));

    if (_storyboard.Children.Count == 0)
    {
        _storyboard.Children.Add(vAnimation);

        Storyboard.SetTargetProperty(vAnimation, new PropertyPath("(Canvas.Top)"));
        Storyboard.SetTarget(vAnimation, _contentPart);                                                           
    }

    _storyboard.Begin();
}