Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
I created Marquee Textblock control in WPF for my app but it was not showing the entire text. I tried to solve where the problem is but i am unable to solve.
Created Marquee textblock control xaml code is
UserControl x:Class="Andhrajyo.MarqueeTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480"

Grid x:Name="LayoutRoot"
<Canvas x:Name="canvas" Background="Transparent" Width="{Binding Width}" Height="{Binding Height}">
<Canvas.Clip>
RectangleGeometry RadiusX="5" RadiusY="5" Rect="400, 400, 400, 400"
</Canvas.Clip>


TextBlock x:Name="textBlock1"
Height="{Binding Height}"
Width="{Binding Width}"
TextWrapping="NoWrap"
Foreground="{Binding Foreground}"
Text="{Binding Text}"
FontSize="{Binding MFontSize}"
</Canvas>
/Grid
/UserControl


Marquee Textblock.xaml.cs is


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Andhrajyo
{
public partial class MarqueeTextBlock : UserControl
{
// storyboard
Storyboard storyboard;

// offset when textBlock1 is long, because user want to see smooth scrolling
private double offset =0;

// default offset
private double defaultOffset =100;

// default velocity
int velocity = 0;

// whether control has beed loaded
// because it's when control is loaded do we start marquee
bool isLoaded = false;

public MarqueeTextBlock()
{
InitializeComponent();

Loaded += MarqueeTextBlock_Loaded;
Unloaded += MarqueeTextBlock_Unloaded;
}

// unload event
void MarqueeTextBlock_Unloaded(object sender, RoutedEventArgs e)
{
// stop marquee when control is unloaded
StopMarquee();
}

// set data context in Loaded
void MarqueeTextBlock_Loaded(object sender, RoutedEventArgs e)
{
if (!isLoaded)
{
// control is loaded
isLoaded = true;

LayoutRoot.DataContext = this;

// resize the clipping
Rect rect = new Rect(0,0, canvas.ActualWidth, canvas.ActualHeight);
RectangleGeometry reo = new RectangleGeometry();
reo.Rect = rect;
this.canvas.Clip = reo;

// always vertical alignment
ChangeOffsetTop();

// this is OK for marquee to start
StartMarquee();
}
else
{
// just run it, after user come to this page again
StartMarquee();
}
}


public void StartMarquee()
{
// first stop all marquee
StopMarquee();

if (ShouldStartMarquee())
{
// change offset
ChangeOffsetLeft(true);

DoAnimationFirst();
}
else
{
// change offset
ChangeOffsetLeft(false);
}
}

public void StopMarquee()
{
if (storyboard != null)
{
storyboard.Stop();
}
}

bool ShouldStartMarquee()
{
return textBlock1.ActualWidth > LayoutRoot.ActualWidth;
}


// after
void storyboard_Completed(object sender, EventArgs e)
{
DoAnimationAfter();

// remeber to unsubscribe
storyboard.Completed += storyboard_Completed;
}


////////////////////////////////////////////////////////////////////////////
// calculate offset
void ChangeOffsetLeft(bool isLong)
{
if (isLong)
{
offset = defaultOffset;
Canvas.SetLeft(textBlock1, offset);
}
else
{
offset = (canvas.ActualWidth - textBlock1.ActualWidth)/2;
Canvas.SetLeft(textBlock1, offset);
}
}

// center vertical
void ChangeOffsetTop()
{
double topOffset = (canvas.ActualHeight - textBlock1.ActualHeight) / 2;
Canvas.SetTop(textBlock1, topOffset);
}

int CalculateDurationFirst()
{
int duration = 45000;



return duration;
}

int CalculateDurationAfter()
{
int duration = 40000;



return duration;
}


void DoAnimationFirst()
{
storyboard = new Storyboard();
TranslateTransform trans = new TranslateTransform() { X = 5.0, Y = 1.0 };
textBlock1.RenderTransformOrigin = new Point(0.5,0.5);
textBlock1.RenderTransform = trans;

// we must calculate the Duration
DoubleAnimation moveAnim = new DoubleAnimation();
int durationFirst = CalculateDurationFirst();
moveAnim.Duration = TimeSpan.FromMilliseconds(durationFirst);

moveAnim.From = 0;
moveAnim.To = -textBlock1.ActualWidth - offset;

Storyboard.SetTarget(moveAnim, textBlock1);
Storyboard.SetTargetProperty(moveAnim, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));

// subscribe to Completed event
storyboard.Completed += new EventHandler(storyboard_Completed);

storyboard.Children.Add(moveAnim);
storyboard.FillBehavior = FillBehavior.HoldEnd;

storyboard.Begin();
}



void DoAnimationAfter()
{
storyboard = new Storyboard();
TranslateTransform trans = new TranslateTransform() { X = 5.0, Y = 1.0 };
textBlock1.RenderTransformOrigin = new Point(0.5, 0.5);
textBlock1.RenderTransform = trans;

// we must calculate the Duration
DoubleAnimation moveAnim = new DoubleAnimation();
int durationAfter = CalculateDurationAfter();
moveAnim.Duration = TimeSpan.FromMilliseconds(durationAfter);

moveAnim.From = canvas.ActualWidth;
moveAnim.To = -textBlock1.ActualWidth - offset;

Storyboard.SetTarget(moveAnim, textBlock1);
Storyboard.SetTargetProperty(moveAnim, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));

storyboard.Children.Add(moveAnim);
storyboard.RepeatBehavior = RepeatBehavior.Forever;
storyboard.FillBehavior = FillBehavior.HoldEnd;

storyboard.Begin();
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dependency property
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MarqueeTextBlock), null);

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

// this doesnot marquee for the first time
// because textBlock1.ActualWidth is 0 !!
if (isLoaded)
{
StartMarquee();
}

}
}

public static readonly DependencyProperty MFontSizeProperty = DependencyProperty.Register("MFontSize",
typeof(int), typeof(MarqueeTextBlock), null);

public int MFontSize
{
get { return (int)this.GetValue(MFontSizeProperty); }
set
{
this.SetValue(MFontSizeProperty, value);
}
}

public static readonly DependencyProperty MTextTrimProperty = DependencyProperty.Register("MTextTrim",
typeof(String), typeof(MarqueeTextBlock), null);

public String MTextTrim
{
get { return (String)this.GetValue(MFontSizeProperty); }
set
{
this.SetValue(MTextTrimProperty, value);
}
}
}
}



My application code which uses the marquee textblock control is

controls2:marqueetextblock x:name="txtT" xmlns:x="#unknown" xmlns:controls2="#unknown">

MFontSize="25"
Width="1000"
Height="80" Margin="20,-10,0,0"
/>
./controls2:marqueetextblock


the text property was set in the code behind

after executing the marquee textblock is not showing the entire text the last text is missing..
the text is long of more than 500 characters
please help me.
Posted
Updated 15-Oct-14 19:02pm
v2
Comments
Sergey Alexandrovich Kryukov 16-Oct-14 1:25am    
Better ask the author of this component. Use the debugger. If the component works poorly, write your own.
Remember that marquee is a bad idea, can a very irritating element. Consider doing some more useful job.
—SA
SureshMarepalli 16-Oct-14 1:37am    
can you please provide your way of doing marquee......

1 solution

SureshMarepalli wrote:

can you please provide your way of doing marquee?
Sure. You can start here: http://msdn.microsoft.com/en-us/library/ms752312%28v=vs.110%29.aspx[^].

These CodeProject article could also be useful:
Beginner's WPF Animation Tutorial[^],
Animation using Storyboards in WPF[^].

But I wanted you: such element can be very annoying; I would prefer to avoid it. Better first test it on yourself and your colleagues, before offering to your users.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900