17,740
社区成员
发帖
与我相关
我的任务
分享
......
using System.Windows.Threading;
namespace Marquee
{
[TemplatePart(Name = "PART_ContentHost", Type = typeof(ContentPresenter))]
public class ProgressControl: ContentControl
{
public int Loop
{
get { return (int)GetValue(LoopProperty); }
set { SetValue(LoopProperty, value); }
}
public static readonly DependencyProperty LoopProperty = DependencyProperty.Register(
"Loop",
typeof(int),
typeof(ProgressControl),
new FrameworkPropertyMetadata(0, OnMarqueeParameterChanged, OnCoerceLoop));
private static object OnCoerceLoop(DependencyObject sender, object value)
{
int loop = (int)value;
if (loop < 0)
{
throw new ArgumentException("Loop必须大于等于0");
}
return value;
}
/// <summary>
/// Gets/Sets the direction of the animation.
/// </summary>
public Direction Direction
{
get { return (Direction)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register(
"Direction",
typeof(Direction),
typeof(ProgressControl),
new FrameworkPropertyMetadata(Direction.Right, OnMarqueeParameterChanged));
/// <summary>
/// Gets/Sets The animation behavior.
/// </summary>
public MarqueeBehavior Behavior
{
get { return (MarqueeBehavior)GetValue(BehaviorProperty); }
set { SetValue(BehaviorProperty, value); }
}
public static readonly DependencyProperty BehaviorProperty = DependencyProperty.Register(
"Behavior",
typeof(MarqueeBehavior),
typeof(ProgressControl),
new FrameworkPropertyMetadata(MarqueeBehavior.Scroll, OnMarqueeParameterChanged));
public double ScrollAmount
{
get { return (double)GetValue(ScrollAmountProperty); }
set { SetValue(ScrollAmountProperty, value); }
}
public static readonly DependencyProperty ScrollAmountProperty = DependencyProperty.Register(
"ScrollAmount",
typeof(double),
typeof(ProgressControl),
new FrameworkPropertyMetadata(10.0, OnMarqueeParameterChanged, OnCoerceScrollAmount));
private static object OnCoerceScrollAmount(DependencyObject sender, object value)
{
double amount = (double)value;
if (amount - double.Epsilon <= 0.0)
{
throw new ArgumentException("ScrollAmount必须大于0");
}
return value;
}
public double ScrollDelay
{
get { return (double)GetValue(ScrollDelayProperty); }
set { SetValue(ScrollDelayProperty, value); }
}
public static readonly DependencyProperty ScrollDelayProperty = DependencyProperty.Register(
"ScrollDelay",
typeof(double),
typeof(ProgressControl),
new FrameworkPropertyMetadata(100.0, OnMarqueeParameterChanged, OnCoerceScrollDelay));
private static object OnCoerceScrollDelay(DependencyObject sender, object value)
{
double delay = (double)value;
if (delay - double.Epsilon <= 0.0)
{
throw new ArgumentException("ScrollDelay必须大于0");
}
return value;
}
private static void OnMarqueeParameterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ProgressControl marquee = sender as ProgressControl;
if (marquee != null)
{
marquee.ResetAnimation();
}
}
private ContentPresenter _contentHost = null;
private int _currentLoop = -1;
private DispatcherTimer _timer = null;
private TranslateTransform _contentTranlate = null;
private int _loopCounter = 1;
private Direction _currentDirection;
static ProgressControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ProgressControl), new FrameworkPropertyMetadata(typeof(ProgressControl)));
ClipToBoundsProperty.OverrideMetadata(typeof(ProgressControl), new FrameworkPropertyMetadata(true));
}
public ProgressControl()
{
this.Loaded += new RoutedEventHandler(Marquee_Loaded);
this.Unloaded += new RoutedEventHandler(Marquee_Unloaded);
_timer = new DispatcherTimer();
_timer.Tick += new EventHandler(Timer_Tick);
}
private void Timer_Tick(object sender, EventArgs e)
{
this.OnUpdateContentPosition();
}
private void Marquee_Loaded(object sender, RoutedEventArgs e)
{
_timer.Start();
}
private void Marquee_Unloaded(object sender, RoutedEventArgs e)
{
_timer.Stop();
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_contentHost = this.GetTemplateChild("PART_ContentHost") as ContentPresenter;
ResetAnimation();
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
this.ResetAnimation();
}
// Clear current animation, and restore content's position
private void ResetAnimation()
{
if (_contentHost != null)
{
if (this.Loop == 0)
{
_currentLoop = -1;
_loopCounter = 0;
}
else
{
_currentLoop = 0;
_loopCounter = 1;
}
_timer.Interval = TimeSpan.FromMilliseconds(this.ScrollDelay);
_currentDirection = this.Direction;
if (this.Direction == Direction.Left)
{
_contentTranlate = new TranslateTransform(this.ActualWidth, 0.0);
}
else if (this.Direction == Direction.Right)
{
_contentTranlate = new TranslateTransform();
}
_contentHost.RenderTransform = _contentTranlate;
}
}
protected virtual void OnUpdateContentPosition() { if (_contentHost != null) { double contentWidth = _contentHost.DesiredSize.Width; double leftBound = 0.0, rightBound = 0.0; if (this.Behavior == MarqueeBehavior.Alternate || this.Behavior == MarqueeBehavior.Slide){leftBound = 0; rightBound = this.ActualWidth - contentWidth; } else if (this.Behavior == MarqueeBehavior.Scroll) {leftBound = -contentWidth; rightBound = this.ActualWidth; } if (_currentLoop < this.Loop) {if (_currentDirection == Direction.Left) { _contentTranlate.X -= this.ScrollAmount; if (_contentTranlate.X <= leftBound) { if (this.Behavior == MarqueeBehavior.Scroll || this.Behavior == MarqueeBehavior.Slide) { _contentTranlate.X = rightBound; }else if (this.Behavior == MarqueeBehavior.Alternate){ _currentDirection = Direction.Right; } _currentLoop += _loopCounter;
}else if (_currentDirection == Direction.Right) { _contentTranlate.X += this.ScrollAmount; if (_contentTranlate.X >= rightBound) { if (this.Behavior == MarqueeBehavior.Scroll || this.Behavior == MarqueeBehavior.Slide) {_contentTranlate.X = leftBound; }else if (this.Behavior == MarqueeBehavior.Alternate) { _currentDirection = Direction.Left; } _currentLoop += _loopCounter;
}
}
}
else { if (_contentTranlate.X < 0) { _contentTranlate.X = 0; }
if (_contentTranlate.X > this.ActualWidth - contentWidth) { _contentTranlate.X = this.ActualWidth - contentWidth; }
}
}
}
}
public enum Direction{Left, Right }
public enum MarqueeBehavior { Scroll, Slide,Alternate }
}
<ResourceDictionary
......
xmlns:local="clr-namespace:Marquee"> <Style TargetType="{x:Type local:ProgressControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ProgressControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}" HorizontalAlignment="Left" Width="{TemplateBinding Width}" ContentSource="Content" ContentTemplate="{TemplateBinding ContentTemplate}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"></ContentPresenter></Border> </ControlTemplate></Setter.Value></Setter></Style></ResourceDictionary>
xmlns:l="clr-namespace:TruthUI"
<l:ProgressControl Direction="Right" Width="352" Height="10" Margin="74,151,74,89" ScrollAmount="10" ScrollDelay="50">
<Image Name="BPImage_ProgressBar_Pic" Style="{StaticResource BPImage_ProgressBar_Pic_RD}"/>
</l:ProgressControl>