animation and data bindings - c#

I need an help with animations, i tried to set by code the value of an SplineDoubleKeyFrame by data binding, but it doesn't work, why?
Code xaml:
<StackPanel Margin="0,435,0,0">
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="barra" Storyboard.TargetProperty="Width">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
<SplineDoubleKeyFrame KeySpline="0,0 1,0" Value="{Binding linea1}" KeyTime="0:0:0.8" />
<SplineDoubleKeyFrame KeySpline="0.10, 0.21 0.00, 1.0" Value="{Binding linea1}" KeyTime="0:0:1.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</StackPanel.Resources>
<Rectangle Fill="White" HorizontalAlignment="Left" Height="72" Margin="12,0,0,0" Grid.Row="1" Stroke="#FF8E76FF" VerticalAlignment="Top" Width="444" StrokeThickness="5"/>
<Rectangle Visibility="Visible" x:Name="barra" Fill="#FF8E76FF" HorizontalAlignment="Left" Height="72" Margin="12,-72,0,0" Stroke="#FF8E76FF" StrokeThickness="5" VerticalAlignment="Top" Width="456"/>
</StackPanel>
c#:
linea1 = 440;
myStoryboard.Begin();
Thanks in advance! ;)

For DataBinding you need to use Property only .you cannot use varibale for binding(for ex: var linea1 = 440;)
To create property I create a class
public class StackpanelProperties
{
public int linea1 { get; set; }
}
And set datacontext to Stackpnael so that I can use this property for binding
this.InitializeComponent();
stack.DataContext = new StackpanelProperties() { linea1 = 440 };
xaml code
<StackPanel Name="stack" Margin="0,435,0,0">
<StackPanel.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Duration="0:0:0.8" EnableDependentAnimation="True" Storyboard.TargetName="barra" Storyboard.TargetProperty="Width">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
<SplineDoubleKeyFrame KeySpline="0,0 1,0" Value="{Binding linea1}" KeyTime="0:0:0.8" />
<SplineDoubleKeyFrame KeySpline="0.10, 0.21 0.00, 1.0" Value="{Binding linea1}" KeyTime="0:0:1.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
<Rectangle Fill="White" HorizontalAlignment="Left" Height="72" Margin="12,0,0,0" Grid.Row="1" Stroke="#FF8E76FF" VerticalAlignment="Top" Width="444" StrokeThickness="5"/>
<Rectangle Visibility="Visible" x:Name="barra" Fill="#FF8E76FF" HorizontalAlignment="Left" Height="72" Margin="12,-72,0,0" Stroke="#FF8E76FF" StrokeThickness="5" VerticalAlignment="Top" Width="456"/>
</StackPanel>
Note : EventTrigger is used for begin animation on stackpnael Loaded event.

Related

Text Box sometimes cursor is missing

I have created a custom water mark text box which is extended from text box. control template for the same is shown below.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:WaterMarkTextBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.15"
Value="0,0,10,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.25"
Value="0,0,-500,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="PART_GridControl"
ClipToBounds="True"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}">
<TextBlock x:Name="PART_PlaceHolderTextBlock"
Style="{StaticResource SWMLightTextBlockStyle}"
Foreground="#BDBBBB"
FontSize="{StaticResource SmallFontSize}"
Text="{TemplateBinding PlaceHolderText}"
VerticalAlignment="Center"
Margin="20,0,10,0" />
<Border Name="border"
CornerRadius="0"
Padding="2"
BorderThickness="1"
BorderBrush="DeepSkyBlue">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<TextBlock x:Name="PART_FieldTextBlock"
HorizontalAlignment="Right"
Foreground="#BDBBBB"
Margin="0,0,-500,0"
Style="{StaticResource SWMLightTextBlockStyle}"
FontSize="{StaticResource SmallFontSize}"
TextWrapping="Wrap"
Text="{TemplateBinding FieldText}"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
but while typing the textbox enters to a condition where it is having no cursor but we can type into it occurs with a probability of 1/2 chars.I wonder how it happens. Anyone is having idea how it is happening?
Two things You can do. First One is Overriding SystemParameters Properties Using reflection Like this
void LocallyDisableMouseVanish()
{
foreach (var field in typeof(SystemParameters).GetFields(BindingFlags.NonPublic|BindingFlags.Static))
if (field.Name.Contains("mouseVanish"))
field.SetValue(null, false);
}
Call this method On Focus Of your Control.
If this is Not working means You can Try something Like this Override the style of the Caret Like this
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:WaterMarkTextBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.15"
Value="0,0,10,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.25"
Value="0,0,-500,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="PART_GridControl"
ClipToBounds="True"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}">
<TextBlock x:Name="PART_PlaceHolderTextBlock"
Style="{StaticResource SWMLightTextBlockStyle}"
Foreground="#BDBBBB"
FontSize="{StaticResource SmallFontSize}"
Text="{TemplateBinding PlaceHolderText}"
VerticalAlignment="Center"
Margin="20,0,10,0" />
<Border Name="border"
CornerRadius="0"
Padding="2"
BorderThickness="1"
BorderBrush="DeepSkyBlue">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
<TextBlock x:Name="PART_FieldTextBlock"
HorizontalAlignment="Right"
Foreground="#BDBBBB"
Margin="0,0,-500,0"
Style="{StaticResource SWMLightTextBlockStyle}"
FontSize="{StaticResource SmallFontSize}"
TextWrapping="Wrap"
Text="{TemplateBinding FieldText}"
VerticalAlignment="Center" />
<Canvas>
<Border x:Name="PART_Caret"
Visibility="Collapsed"
Canvas.Left="0"
Canvas.Top="0"
Width="5"
Height="25"
Background="Black"
BorderThickness="1">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard x:Name="CaretStoryBoard"
RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Background.Color"
Duration="0:0:0:1"
FillBehavior="HoldEnd">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0.750"
Value="Transparent" />
<DiscreteColorKeyFrame KeyTime="0:0:0.000"
Value="Black" />
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</Canvas>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="CaretBrush "
Value="Transparent" />
And in your control code Add this
public override void OnApplyTemplate()
{
this.border = this.GetTemplateChild("PART_Caret") as Border;
base.OnApplyTemplate();
}
And add this Method
private void MoveCustomCaret()
{
var caretLocation = this.GetRectFromCharacterIndex(this.CaretIndex).Location;
if (!double.IsInfinity(caretLocation.X))
{
Canvas.SetLeft(border, caretLocation.X);
}
if (!double.IsInfinity(caretLocation.Y))
{
Canvas.SetTop(border, caretLocation.Y);
}
}
And Finally Call This method and set the visibility of the border
private void SWMTextBox_GotFocus(object sender, RoutedEventArgs e)
{
MoveCustomCaret();
border.Visibility = Visibility.Visible;
}
also in TextChangedEvent
private void CustomTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
MoveCustomCaret();
}
And Hid the Visibility in Lost_Focus_Event
private void SWMTextBox_LostFocus(object sender, RoutedEventArgs e)
{
border.Visibility = Visibility.Hidden;
}

How to add objects to Canvas after ellipse reaches middle of the Canvas?

I am animating the ellipse to move horizontally in wpf. Now I want to add few more ellipses on to the canvas when ellipse reaches certain point on canvas (let's say midpoint of the canvas). How can I achieve this?
XAML code-
<Canvas Background="AliceBlue" x:Name="canvas">
<Ellipse
Name="ellipse1"
Canvas.Left="50"
Fill="#FFFFFF00"
Height="75"
Width="100"
/>
</Canvas>
Code behind-
public partial class MainWindow : Window
{
private DoubleAnimation anim = new System.Windows.Media.Animation.DoubleAnimation(50, 400, TimeSpan.FromSeconds(10),
System.Windows.Media.Animation.FillBehavior.HoldEnd);
private AnimationClock clock;
public MainWindow()
{
InitializeComponent();
clock = anim.CreateClock();
this.ellipse1.ApplyAnimationClock(Canvas.LeftProperty, clock);
}
}
Initially I thought it was simple, I would just access Canvas.Left from code behind and when it reaches the value I want, I would add the ellipses. But I am struggling to implement this, I guess I would need some kind of watcher or event to achieve this. How should I implement it?
Create two storyboards. Each one does half the animation. When the first storyboard completes start the second storyboard and add the other ellipses.
XAML
<Window.Resources>
<Storyboard x:Key="StartingStoryboard"
Completed='Storyboard_Completed'>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="ellipse1">
<EasingDoubleKeyFrame KeyTime="0"
Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2"
Value="100" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="EndingStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="ellipse1">
<EasingDoubleKeyFrame KeyTime="0"
Value="100" />
<EasingDoubleKeyFrame KeyTime="0:0:2"
Value="200" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource StartingStoryboard}" />
</EventTrigger>
</Window.Triggers>
<Canvas Background="AliceBlue"
x:Name="canvas1">
<Ellipse Name="ellipse1"
Fill="#FFFFFF00"
Height="75"
Width="100"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
Code
private void Storyboard_Completed(object sender, EventArgs e) {
var sb = FindResource("EndingStoryboard") as Storyboard;
sb.Begin();
var orangeEllipse = new Ellipse();
orangeEllipse.Fill = new SolidColorBrush(Colors.Orange);
orangeEllipse.Width = orangeEllipse.Height = 40;
canvas1.Children.Add(orangeEllipse);
}

InputDialog positioning issue

In a windows store app, i have the following page
<common:LayoutAwarePage
x:Class="Gapp_metro.Pages.DocumentsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Gapp_metro.Pages"
xmlns:common="using:Gapp_metro.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Style="{StaticResource RootGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid Style="{StaticResource HeaderGridStyle}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Click="GoBack" IsEnabled="{Binding Frame.CanGoBack}" Style="{StaticResource BackButtonStyle}" />
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Title}" Style="{StaticResource PageHeaderTextStyle}" />
</Grid>
<Grid Grid.Row="1" Style="{StaticResource ContentGridStyle}" VerticalAlignment="Center">
<GridView x:Name="gridView" Grid.Row="1" ItemsSource="{Binding Tiles}" Style="{StaticResource GridViewStyle}" ItemClick="OnItemClick" />
<ListView x:Name="listView" Grid.Row="1" ItemsSource="{Binding Tiles}" Style="{StaticResource ListViewStyle}" ItemClick="OnItemClick"
Visibility="Collapsed" />
<ProgressRing x:Name="ProgressR" Grid.Row="1" IsActive="{Binding IsLoading}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape" />
<VisualState x:Name="Filled"/>
<VisualState x:Name="FullScreenPortrait" />
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="gridView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="listView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<Page.BottomAppBar>
<AppBar x:Name="appBar" Style="{StaticResource AppBarStyle}">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Click="OnAddButtonClick" Style="{StaticResource AddAppBarButtonStyle}" />
<Button Click="OnUploadButtonClick" Style="{StaticResource UploadAppBarButtonStyle}" />
<Button Click="OnPhotoButtonClick" Style="{StaticResource PhotoAppBarButtonStyle}" />
</StackPanel>
</AppBar>
</Page.BottomAppBar>
and in my code behind i have this function for the "Click="OnAddButtonClick""
private async void OnAddButtonClick(object sender, RoutedEventArgs e)
{
var dialog = new InputDialog();
dialog.BackgroundStripeBrush = new SolidColorBrush(Color.FromArgb(255, 149, 191, 0));
dialog.Background = new SolidColorBrush(Color.FromArgb(255, 149, 191, 0));
dialog.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 149, 191, 0));
Style buttonStyle = new Style() { TargetType = typeof(Button) };
buttonStyle.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
dialog.ButtonStyle = buttonStyle;
var result = await dialog.ShowAsync(App.Current.Resources["createFolder"] as String, App.Current.Resources["newFolderName"] as String, App.Current.Resources["create"] as String, App.Current.Resources["close"] as String);
dialog.VerticalAlignment = VerticalAlignment.Top;
dialog.Margin = new Thickness(0, 0, 0, 0);
....
but when i press the add button, the input dialog always appears in the center of screen, even tho i tried to add a vertical alignment and margins.
pretty sure im missing something silly
how do i make it appear on the top ?
You should set VerticalAlignment and Margin before calling ShowAsync.

C# WPF pausing an animated window with storyboard

I am making a C# wpf application with Visual Studio 2012. Here is the toast like notification. It is animated to go off by 4 seconds. It I get the mouse over this I want to pause the animation.
How can I achieve that ?
<Window x:Class="Exmaple.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
Title="Notification Popup" Width="300" SizeToContent="Height"
WindowStyle="None" AllowsTransparency="True" Height="Auto" Background="Transparent">
<Grid x:Name="abc" RenderTransformOrigin="0,1" Height="Auto" Width="300" Margin="0,0,0,0" MouseEnter="Grid_MouseEnter_1" >
<!-- Notification area -->
<Border BorderThickness="1" Background="#FF2D2D30" BorderBrush="Black" CornerRadius="0" Margin="0,0,0,0">
<!--StackPanel Margin="20"-->
<TextBlock x:Name="textblocknotify" TextWrapping="Wrap" Height="Auto" Margin="5" Foreground="White">
</TextBlock>
<!--CheckBox Content="Checkable" Margin="5 5 0 5" /-->
<!--Button Content="Clickable" HorizontalAlignment="Center" /-->
<!--/StackPanel-->
</Border>
<!-- Animation -->
<Grid.Triggers >
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Completed="Storyboard_Completed_1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:4.5" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Completed="Storyboard_Completed_1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:4.5" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.RenderTransform>
<ScaleTransform ScaleY="1" />
</Grid.RenderTransform>
</Grid>
Code behind this
public partial class Window1 : Window
{
public Window1(String s)
{
InitializeComponent();
textblocknotify.Text = s;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
var workingArea = System.Windows.SystemParameters.WorkArea;
var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom));
this.Left = corner.X - this.ActualWidth - 10;
this.Top = corner.Y - this.ActualHeight-30;
}));
//this.Close();
}
private void Storyboard_Completed_1(object sender, EventArgs e)
{
this.Close();
}
private void Grid_MouseEnter_1(object sender, MouseEventArgs e)
{
//don't know what to do
}
You can use the PauseStoryboard Class and the UIElement.MouseEnter Event to pause a running Animation. Equally, if you want the Animation to resume when the mouse is no longer over the control, then you can use the ResumeStoryboard Class and the UIElement.MouseLeave Event. Here is a simple example to demonstrate:
<Button Content="Click Me">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Name="OpacityStoryboard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)"
From="0" To="1" RepeatBehavior="Forever" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<PauseStoryboard BeginStoryboardName="OpacityStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<ResumeStoryboard BeginStoryboardName="OpacityStoryboard" />
</EventTrigger>
</Button.Triggers>
</Button>

Label freezes and doesn't change it's Left property

Basically I tried to make a marquee with 2 Labels that when one goes invisible, the second one starts it's animation so it goes smooth from left to right and the text is always visible. My problem is that it does work at start but when I retry that code (second time at run time so the old animation stops, it refresh the text and start the animation again) the second label freezes when it was and it's left property of it's canvas doesn't change (Canvas.SetLeft(L_Content_Second, -L_Content_Second.ActualWidth))
C#
it's a function called StartAnimation(); It's fired when content of L_Content and L_Content_Second changes
DoubleKeyFrameCollection collection = new DoubleKeyFrameCollection();
collection.Add(
new LinearDoubleKeyFrame(
-L_Content.ActualWidth,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0)))
);
if (L_Content.ActualWidth > this.ActualWidth)
{
collection.Add(
new LinearDoubleKeyFrame(
this.ActualWidth - (L_Content.ActualWidth / 2),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(15)))
);
collection.Add(
new LinearDoubleKeyFrame(
this.ActualWidth * 2,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(30)))
);
}
else
{
collection.Add(
new LinearDoubleKeyFrame(
this.ActualWidth - L_Content.ActualWidth,
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(15)))
);
collection.Add(
new LinearDoubleKeyFrame(
this.ActualWidth + (this.ActualWidth - L_Content.ActualWidth),
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(30)))
);
}
animK.KeyFrames = collection;
animK.Duration = TimeSpan.FromSeconds(30);
animK2.KeyFrames = collection;
animK2.BeginTime = TimeSpan.FromSeconds(15);
animK2.Duration = TimeSpan.FromSeconds(30);
animK.AutoReverse = false;
animK2.AutoReverse = false;
animK.FillBehavior = FillBehavior.Stop;
animK.RepeatBehavior = RepeatBehavior.Forever;
animK2.FillBehavior = FillBehavior.Stop;
animK2.RepeatBehavior = RepeatBehavior.Forever;
Canvas.SetLeft(L_Content_Second, -L_Content_Second.ActualWidth); //This works at start, then it doesn't any more
L_Content_Second.Visibility = System.Windows.Visibility.Visible;
L_Content.BeginAnimation(Canvas.LeftProperty, animK, HandoffBehavior.SnapshotAndReplace);
L_Content_Second.BeginAnimation(Canvas.LeftProperty, animK2, HandoffBehavior.SnapshotAndReplace);
XAML
<UserControl x:Name="userControl" x:Class="Supreme.Components.ScrollLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="18" Width="300" MouseDoubleClick="UserControl_MouseDoubleClick_1" Background="#00000000">
<Canvas x:Name="Container">
<Label x:Name="L_Content" Content="" HorizontalAlignment="Left" Padding="0" Height="18" Foreground="{Binding Foreground, ElementName=userControl}" VerticalAlignment="Top"/>
<Label x:Name="L_Content_Second" Content="" HorizontalAlignment="Left" Padding="0" Height="18" Foreground="{Binding Foreground, ElementName=userControl}" SizeChanged="L_Content_SizeChanged" VerticalAlignment="Top"/>
</Canvas>
</UserControl>
I tried to attempt the same via XAML
below is the sample for same, run it and see if this does what you are looking for.
<Canvas x:Name="Container">
<Canvas.Resources>
<l:PositionConverter xmlns:l="clr-namespace:CSharpWPF"
x:Key="PositionConverter" />
<Storyboard x:Key="marquee">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L_Content"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:10">
<SplineDoubleKeyFrame KeyTime="0:0:0"
Value="{Binding ActualWidth, ElementName=L_Content, Converter={StaticResource PositionConverter}}" />
<SplineDoubleKeyFrame KeyTime="0:0:5"
Value="{Binding ActualWidth,ElementName=Container}" />
<SplineDoubleKeyFrame KeyTime="0:0:10"
Value="{Binding ActualWidth,ElementName=Container}" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="L_Content_Second"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:10">
<SplineDoubleKeyFrame KeyTime="0:0:0"
Value="{Binding ActualWidth, ElementName=L_Content_Second, Converter={StaticResource PositionConverter}}" />
<SplineDoubleKeyFrame KeyTime="0:0:5"
Value="{Binding ActualWidth, ElementName=L_Content_Second, Converter={StaticResource PositionConverter}}" />
<SplineDoubleKeyFrame KeyTime="0:0:10"
Value="{Binding ActualWidth,ElementName=Container}" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Canvas.Resources>
<TextBox x:Name="L_Content"
Foreground="Red"
Text="first" />
<TextBox x:Name="L_Content_Second"
Foreground="Green"
Text="second">
</TextBox>
<Button Content="Start" Canvas.Top="30">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource marquee}" />
</EventTrigger>
</Button.Triggers>
</Button>
<Canvas.Triggers>
<EventTrigger SourceName="L_Content"
RoutedEvent="SizeChanged">
<BeginStoryboard Storyboard="{StaticResource marquee}" />
</EventTrigger>
<EventTrigger SourceName="L_Content_Second"
RoutedEvent="SizeChanged">
<BeginStoryboard Storyboard="{StaticResource marquee}" />
</EventTrigger>
<EventTrigger RoutedEvent="SizeChanged">
<BeginStoryboard Storyboard="{StaticResource marquee}" />
</EventTrigger>
</Canvas.Triggers>
</Canvas>
I've used textbox in this example for easy value change, also for this I have created a converter
namespace CSharpWPF
{
public class PositionConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return -System.Convert.ToDouble(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

Categories