문제

Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang Gaurang

I am working in WPF to create a text ticker. I am able to move the text from right to left forever but my problem is, that I want to move the same text seamlessly to create the above effect(Just like the stock exchange ticker). The above text must move endlessly.

How can I achieve it?

도움이 되었습니까?

해결책

So from reading your question i'm not really sure what you want. Do you want a text, that scrolls out of the textbox, and starts over, like most marquee controls/functions.

Or do you want some text that runs over and over in your textbox, filling it out from start till end? and then with a given loop that is undectectable? :)

Code behind:

//Single line animation.

private void LeftToRightMarqueeOnTextBox()
{
  string Copy = " "+TextBoxMarquee.Text;
  double TextGraphicalWidth = new FormattedText(TextBoxMarquee.Text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(TextBoxMarquee.FontFamily.Source), TextBoxMarquee.FontSize, TextBoxMarquee.Foreground).WidthIncludingTrailingWhitespace;
  //BorderTextBoxMarquee.Width = TextGraphicalWidth + 5;

  ThicknessAnimation ThickAnimation = new ThicknessAnimation();
  ThickAnimation.From = new Thickness(TextBoxMarquee.ActualWidth, 0, 0, 0);
  ThickAnimation.To = new Thickness(-TextGraphicalWidth, 0, 0, 0);
  ThickAnimation.RepeatBehavior = RepeatBehavior.Forever;
  ThickAnimation.Duration = new Duration(TimeSpan.FromSeconds(3));
  TextBoxMarquee.BeginAnimation(TextBox.PaddingProperty, ThickAnimation);
}

OR

//Sentence Repeat animation with no gaps.

string Copy = " "+TextBoxMarquee.Text;
  double TextGraphicalWidth = new FormattedText(Copy, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(TextBoxMarquee.FontFamily.Source), TextBoxMarquee.FontSize, TextBoxMarquee.Foreground).WidthIncludingTrailingWhitespace;
  double TextLenghtGraphicalWidth = 0;
  //BorderTextBoxMarquee.Width = TextGraphicalWidth + 5;
  while (TextLenghtGraphicalWidth < TextBoxMarquee.ActualWidth)
  {
    TextBoxMarquee.Text += Copy;
    TextLenghtGraphicalWidth = new FormattedText(TextBoxMarquee.Text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(TextBoxMarquee.FontFamily.Source), TextBoxMarquee.FontSize, TextBoxMarquee.Foreground).WidthIncludingTrailingWhitespace;
  }
  TextBoxMarquee.Text += " "+TextBoxMarquee.Text;
  ThicknessAnimation ThickAnimation = new ThicknessAnimation();
  ThickAnimation.From = new Thickness(0, 0, 0, 0);
  ThickAnimation.To = new Thickness(-TextGraphicalWidth, 0, 0, 0);
  ThickAnimation.RepeatBehavior = RepeatBehavior.Forever;
  ThickAnimation.Duration = new Duration(TimeSpan.FromSeconds(2));
  TextBoxMarquee.BeginAnimation(TextBox.PaddingProperty, ThickAnimation);

XAML:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Canvas ClipToBounds="True" Name="canMain" Background="Transparent">
        <Grid Width="{Binding ElementName=canMain, Path=ActualWidth}" >
            <Grid.ColumnDefinitions>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Name="TextBlockMarquee" Text="This is my animated text" />
            <Border Grid.Row="1" BorderBrush="Black" BorderThickness="1">
                <TextBox ClipToBounds="True" Name="TextBoxMarquee" Text="lars er en god skakspiller, der tænker længere end de andre" BorderBrush="Transparent"/>
            </Border>
        </Grid>
    </Canvas>
</Grid>

Basically ignore most of the XAML. Whats important is the lenght of the Text in the Textbox. Havn't found a generic solution, thats why my From Thickness is number based.

But just had to be sure that this was what you were looking for :)

EDIT/UPDATE:

So try it out now, i've updated the code.. Hopefully it works, but from a few test it seemed like it :) Only thing that you need to be sure of is that the entire textbox is filled out, then i'm doing a copy of it, and i'll loop the two text from the strings graphical lenght :)(

EDIT/UPDATE: I've added my final solutions hope this was of any help.

EDIT/Update

Forgot to update my Repeat solution so it didn't cut off and make the loops visible.. Done now :)

다른 팁

I would create multiple ContentControls (or whatever controls you want to use) and put them in a StackPanel with horizontal direction. The number of ContentControls depends on the size of the content. Therefore, I would create one ContentControl, assign the content, and then call Measure(...) on it to determine the size it needs. Depending on the size of the window or parent control, you can calculate how many controls you need to create to fill the entire space. This would look something like this:

Initial state (1):  +------------- Parent Control -------------+
                    |                                          |
                    |+---------+ +---------+ +---------+ +-----|---+ +---------+
                    || Gaurang | | Gaurang | | Gaurang | | Gaur|ng | | Gaurang |
                    |+---------+ +---------+ +---------+ +-----|---+ +---------+
                    |                                          |^^^^^^^^^^^^^^^^
                    +------------------------------------------+  not visible!

Then I would put the StackPanel with the ContentControls into a Canvas and animate the StackPanel's Canvas.Left property, so that it moves into the desired direction.

Now the problem is that the end of the StackPanel will move into the visible area and there will be no more ContentControl to show:

Bad state (2):      +------------- Parent Control -------------+
                    |                                          |
+---------+ +-------|-+ +---------+ +---------+ +---------+    |
| Gaurang | | Gauran| | | Gaurang | | Gaurang | | Gaurang |    |
+---------+ +-------|-+ +---------+ +---------+ +---------+    |
^^^^^^^^^^^^^^^^^^^^|                                          |
     not visible    +------------------------------------------+
                                                           ^^^^
                                                            BAD

You can fix this by restricting the animation of the StackPanel's Canvas.Left property, so that it only moves until the first ContentControl was moved out of the visible area:

Final state (3):    +------------- Parent Control -------------+
                    |                                          |
         +---------+|+---------+ +---------+ +---------+ +-----|---+
         | Gaurang ||| Gaurang | | Gaurang | | Gaurang | | Gaur|ng |
         +---------+|+---------+ +---------+ +---------+ +-----|---+
                    |                                          |
                    +------------------------------------------+

Once this state is reached, the animation should start from the beginning, i.e. go back to the initial state (1). This way, you will always animate between state (1) and state (3). Since all ContentControls have the same size, the user gets the impression of an infinitely moving animation. Of course, the animation should be configured to repeat infinitely.

Note: I did not test this, but I think it should work. Now I did test it, and it works. Here is my test code:

<Canvas>
    <StackPanel x:Name="stack" Orientation="Horizontal">
        <StackPanel.Triggers>
            <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation
                            Storyboard.TargetProperty="(Canvas.Left)"
                            From="0" To="-68"
                            FillBehavior="Stop" RepeatBehavior="Forever"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </StackPanel.Triggers>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
        <ContentControl Content="Gaurang" Margin="4" Width="60"/>
    </StackPanel>
</Canvas>

Paste this into a blank WPF Window and run it. You can increase the size of the window to see what really happens - the animation only moves by one ContentControl and then starts from the beginning.

Note that the To="-68" is calculated using Width + Margin.Left + Margin.Right. In your case, you would have to add the ContentControls manually in code-behind, determine their width and set the animation's To property accordingly.

I created an application to display RSS feeds as a ticker that moves right to left just like a stock ticker. It should be trivial to modify it to be a stock ticker instead. RumorMill4

The link has a brief tutorial and all the source code, but the one thing you will need to know is this ticker works off a Queue, so once an item has scrolled off it is De-queued. At that time you could check if the data is still relevant and update it then add it back to the queue for display.

Unfortunately this implementation does not support DataBinding so you cannot adjust the values while the ticker is currently moving the item. (wrote it years ago, and RSS feeds don't change like stocks do, so wasn't a priority.)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top