Trouble creating horizontal automatic scrolling textblock

1.2k views Asked by At

I'm trying to create an automatic scrolling textblock.

This is the code I have so far:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="150" Width="400">
<Grid HorizontalAlignment="Stretch">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="50"></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <StackPanel Background="Red" Grid.Column="0" />

    <StackPanel x:Name="UserContainer" Grid.Column="1">
        <TextBlock x:Name="UserStatusLabel" TextWrapping="NoWrap" VerticalAlignment="Top"><Run Language="nl-nl" Text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit."/>
        <TextBlock.RenderTransform>
          <TranslateTransform x:Name="translate" />
            </TextBlock.RenderTransform>
              <TextBlock.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard>
                        <Storyboard RepeatBehavior="Forever">
                            <DoubleAnimation
                                From="{Binding ElementName=UserContainer, Path=Width}" To="-200"
                                Storyboard.TargetName="translate"
                                Storyboard.TargetProperty="X"
                                Duration="0:0:3"
                                AutoReverse="True" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </TextBlock.Triggers>
        </TextBlock>
    </StackPanel>
    <StackPanel Background="Blue" Grid.Column="2" />
</Grid>

But I have 3 problems:

  • The text should be scrolled to the left till the end. Now it stops at a certain point
  • The text should not cross the red container at the left, it shouldn't run trough it.
  • The text is cut off at a certain point, but I don't know why.
2

There are 2 answers

2
Sheridan On BEST ANSWER

First, you need to add ClipToBounds="True" to you central StackPanel to stop the text from showing after it leaves the bounds of the StackPanel.

Secondly, the text stops at a 'certain distance' as you say because you told it to by setting the DoubleAnimation to only move to -200. We need to replace that with the actual value of the StackPanel.ActualWidth property:

<DoubleAnimation To="{Binding ActualWidth, ElementName=UserContainer}" 
    Storyboard.TargetName="translate" Storyboard.TargetProperty="X" Duration="0:0:3" 
    AutoReverse="True" />

However, this moves the text to the right edge instead. I'm going to give this to you as an answer for now and if I can think of an easy way to reverse the direction of movement, I'll come back and edit it later.

UPADTE >>>

Ok, so the easiest thing to make the text move left is to implement a simple Converter:

public class AdditiveInverseDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(double) && targetType != typeof(double)) return false;
        return -(double)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(double) && targetType != typeof(double)) return false;
        return -(double)value;
    }
}

Then change your XAML:

<DoubleAnimation To="{Binding ActualWidth, ElementName=UserContainer, Converter={
    StaticResource AdditiveInverseDoubleConverter}}" Storyboard.TargetName="translate" 
    Storyboard.TargetProperty="X" Duration="0:0:3" AutoReverse="True" />

Don't forget to add the XML Namespace:

xmlns:Converters="clr-namespace:WpfApplication1.Converters"

And Resource:

<Window.Resources>
    <Converters:AdditiveInverseDoubleConverter x:Key="AdditiveInverseDoubleConverter" />
</Window.Resources>

UPDATE 2 >>>

Ah, I just worked it out... the TextBlock is cut off because it won't fit into the StackPanel otherwise... making the StackPanel bigger makes more text appear. However, the answer is to not use the StackPanel and use a Canvas instead... this shows all of the text.

0
user007 On

The issue is that with Render Transform you are transforming only what has been rendered, and your text has been cut at that point. LayoutTransform ignores TranslateTransform, so you cant use it here, but if you were using RotateTransform you would see the rest of the text appearing. Not sure how you can achieve your goal with Render Transform.

            <TextBlock.LayoutTransform>
                <RotateTransform  x:Name="translate" />
            </TextBlock.LayoutTransform>
            <TextBlock.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard>
                        <Storyboard RepeatBehavior="Forever">
                            <DoubleAnimation
                            From="0" To="90"
                            Storyboard.TargetName="translate"
                            Storyboard.TargetProperty="Angle"
                            Duration="0:0:3"
                            AutoReverse="True" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </TextBlock.Triggers>

Edit: What about Margin animation, its working fine:

<ThicknessAnimation
     Storyboard.TargetName="UserStatusLabel"
     Storyboard.TargetProperty="Margin"
     Duration="0:0:3" AutoReverse="True"  From="0,0,0,0" To="-200,0,0,0" />