animating an observablecollection move operation in the UI wpf? - c#

I have a wrappanel bound to an observablecolelction.
Is there a way to animate the movement of items in the UI when the collection is changed in the code behind? Kind of like the fluid movement of windows tiles style metro apps?
Any design ideas of how to go about this will be appreciated.
Right now, all I can think of is animating the layout chaging event?
Thanks

I've needed such thing in the past and -as I remember- I ended using a slightly modified version of the sample provided here:
https://learn.microsoft.com/en-us/archive/blogs/devdave/layout-transitions-an-animatable-wrappanel
This sample is somewhat advanced and supports animating the items when any modification is made to the collection (adding items, deleting items, resizing the panel)
On the other hand if what you need is a simple animation at the item level only (e.g. when an item is appearing/disappearing) it's much simpler you can build an ItemTemplate with a control that has an EventTrigger for the relevant event. This example will animate the item when added:
XAML:
<StackPanel>
<ItemsControl x:Name="itemsControl" Height="300">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Width="80" Height="80" Fill="Red" Margin="4" Opacity="0">
<Rectangle.RenderTransform>
<TranslateTransform Y="20" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.6" />
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).Y" To="0" Duration="00:00:00.4" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Width="60" Height="40" Content="Add Item" Click="Button_Click" />
</StackPanel>
Code behind:
ObservableCollection<string> items = new ObservableCollection<string>();
public MainWindow()
{
InitializeComponent();
itemsControl.ItemsSource = items;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
items.Add("New Item");
}

Related

Wizard control for UWP

I'm looking for a sample wizard control for UWP. I am looking for a control that uses forward and backward buttons to transition from one panel to the next.
I have tried to implement my own by animating the width of panels in a horizontally oriented StackPanel, but it doesn't work as expected (the width is not animated and reverts back).
<Page.Resources>
<Storyboard x:Name="GoToNextAnimation" Storyboard.TargetName="LeftPanel">
<DoubleAnimation Storyboard.TargetProperty="Width" From="100" To="0" AutoReverse="False" Duration="0:0:1" />
</Storyboard>
</Page.Resources>
<StackPanel Orientation="Horizontal" Width="100" Tapped="StackPanel_Tapped" Background="Red" Height="50">
<Button x:Name="LeftPanel" Background="Yellow" Width="100" Height="50" />
<Button x:Name="RightPanel" Background="Green" Width="100" Height="50" />
</StackPanel>
with the event handler beginning the animation:
bool isLeft = true;
private void StackPanel_Tapped(object sender, TappedRoutedEventArgs e)
{
if (isLeft)
{
GoToNextAnimation.Begin();
}
else
{
LeftPanel.Width = 100;
}
isLeft = !isLeft;
}
When I tep the control it briefly (much quicker than the animation is intended to run for) changes to the red color (background of StackPanel) before reverting back to yellow (*never showing the green for the RightPanel).

WPF Stock Ticker/Animate item within ItemTemplate

I am trying to create a user control similar to a stock ticker. It will slowly scroll the items to the left. So far I am unable to get something going because:
I am new to WPF/XAML and everywhere I search seems to apply to
silvelight
I am using an ItemTemplate within a ItemsControl, and cant find any
examples showing how to add a storyboard for a item within an item template.
here is my XAML:
<UserControl x:Class="WpfApplication.Ctrls.MessageTicker"
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"
xmlns:ctrls="clr-namespace:WpfApplication.Ctrls"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="Honeydew">
<ItemsControl ItemsSource="{Binding}" Name="_items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="_panel">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Grid.RenderTransform).(TranslateTransform.X)"
Storyboard.TargetName="_panel"
From="0"
To="360"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Word}" Grid.Column="0" Margin="0" FontWeight="Normal" FontFamily="Segoe UI Semibold"/>
<TextBlock Text="{Binding Path=Percent}" Grid.Column="1" Margin="5,0,3,0" FontFamily="Segoe UI Mono" Foreground="Blue"/>
<Polygon Points="0,10 5,0 10,10" Stroke="Black" Fill="Green" Grid.Column="2" Margin="0,3,10,0"/>
<Polygon Points="5,10 10,0 0,0" Stroke="Black" Fill="Red" Grid.Column="2" Visibility="Collapsed"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
From what I have read, I should be putting the storyboard within the template. When I add a new item to the ItemsControl, nothing happens. I need to have it start at the end of the ItemsControl and scroll to the right all the way to the beginning of the ItemsControl.
Ok so you're close, but you're missing some key things that might explain why it's not firing as you'd expect.
So your first issue lies with how you're using _panel. We'll want to actually move that to an RenderTransform on this Grid that's acting as your parent.
So instead of;
<Grid x:Name="_panel">
We'll say;
<Grid>
<Grid.RenderTransform>
<TranslateTransform x:Name="_panel">
</Grid.RenderTransform>
...
Because your TargetProperty setting in your storyboard isn't going to magically append that Transform on demand like it looks you're thinking it might (at least I've never seen it done that way I don't think).
So we have that, now let's go talk to that Transform via your Storyboard and have it talk to an actual property of your Transform thusly;
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="X"
Storyboard.TargetName="_panel">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="360" />
</DoubleAnimation>
</Storyboard>
So what we're doing is basically saying "HEY _panel, guess what? You get to animate, and before you start I want you to know you're moving 360 across your X axis"
We could add a keytime here to make this happen over more keyframes to allow it to fill in the blanks of an actual animation sequence (your ticker anime, hint hint) but for now, we're just telling that bugger to move.
Other than that, you should work. Hope this helps, cheers.
Oh and PS, you'd be surprised how much XAML can work between WPF/SL/WP, etc. etc. if you just know the fundamentals. Best of luck!

Binding to ObservableCollection with transition

I have ItemsControl which I bind to ObservableCollection
On my view model I just insert object and it pops onto UI
I want to show transition. For example, I want this item to fade in so user registers this change visually, let's say it happens in 1 second.
What should I look for? How it's done in WPF?
EDIT:
I think I need some kind of animation but what I'm looking for is something simple without coding. Plain XAML implementation, is anything built-in? I tried TranslateTransform and other choices but it doesn't do anything.
<ItemsControl ItemsSource="{Binding Source={StaticResource TrucksSource}}">
<ItemsControl.RenderTransform>
<TranslateTransform />
</ItemsControl.RenderTransform>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TruckId}" Background="Aqua"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
For fade-in, you can use an EventTrigger on the Loaded event for the ContentPresenters
<ItemsControl ItemsSource="{Binding Source={StaticResource TrucksSource}}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard Storyboard.TargetProperty="Opacity">
<DoubleAnimation From="0.0"
To="1.0"
Duration="00:00:01"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TruckId}" Background="Aqua"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Read this: http://msdn.microsoft.com/en-us/library/ms750596.aspx
You need Animating Transformations (last chapter) and change Opacity value from 1.0 to 0.0

WPF UserControl Animation wont work..?

I'm really new to WPF so if you can point me to a tutoiral as well i will be very happy :)
here is my curreny code:
<Grid Name="Grid">
<local:Card Loaded="Card_Loaded"
x:Name="MyCard">
<local:Card.Triggers>
<EventTrigger RoutedEvent="local:Card.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyCard"
Storyboard.TargetProperty="Opacity"
From="1.0"
To="0.0"
Duration="0:0:5"
AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</local:Card.Triggers>
</local:Card>
</Grid>
local:Card is a UserControl
Here is why i use x:Name="" and not Name="":
Because 'MS.Internal.Design.Metadata.ReflectionTypeNode' is implemented in the same assembly, you must set the x:Name attribute rather than the MS.Internal.Design.Metadata.ReflectionPropertyNode attribute.
And i can see the Card and everything but the Animation doesn't work =\
Here is the card XAML:
<UserControl.Resources>
<x:Array Type="{x:Type s:String}"
x:Key="src">
<s:String>Foo</s:String>
</x:Array>
<DataTemplate x:Key="frontTemplate">
<Grid Background="Transparent">
<Image Source="Images\Card.jpg" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="backTemplate">
<GroupBox Header="Back"
Background="White">
<StackPanel>
<RadioButton Content="This"
IsChecked="True" />
<RadioButton Content="Is" />
<RadioButton Content="The" />
<RadioButton Content="Back" />
</StackPanel>
</GroupBox>
</DataTemplate>
</UserControl.Resources>
<ScrollViewer>
<ItemsControl Width="180"
Height="250"
ItemsSource="{StaticResource src}"
ItemTemplate="{StaticResource flipItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
I copied your XAML exactly and ran it in a window. The only change I made was to replace the local:Card object with a TextBlock (since I didn't have a Card usercontrol). The animation ran perfectly.
So either your local:Card object has something strange that isn't allowing the animation to work or the Loaded="Card_Loaded" method in this line:
<local:Card Loaded="Card_Loaded" x:Name="MyCard">
is interfering with the event trigger:
<EventTrigger RoutedEvent="local:Card.Loaded">
Put the storyboard in either the EventTrigger.EnterActions or EventTrigger.Actions tags.
I recently dived in to some WPF animations....here's the link that got me started:
http://www.galasoft.ch/mydotnet/articles/article-2006102701.aspx
Solution:
<Grid Name="Grid">
<local:Card x:Name="MyCard" MouseEnter="MyCard_MouseEnter" />
</Grid>
<Window.Resources>
<Storyboard x:Key="sbdCardAnim">
<DoubleAnimation
Storyboard.TargetName="MyCard"
Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</Window.Resources>
C#:
private void MyCard_MouseEnter(object sender, MouseEventArgs e)
{
Storyboard sbdCardAnim = (Storyboard)FindResource("sbdCardAnim");
sbdCardAnim.Begin(this);
}

want a silverlight listbox with vertical marquee like effect

i want a silverlight listbox whose items are automatic scrollable (like a vertical marquee)
You might try using an ItemsControl setting the ItemsControl.ItemPanel to a StackPanel with a TranslateTransform applied on it. Then you can have a running Storyboard that adjusts the position of the Y coordinate of the Translate Transform.
EDIT: Example
<Border BorderBrush="Black" BorderThickness="2"
Height="100" Width="100"
HorizontalAlignment="Left" VerticalAlignment="Top" >
<Border.Clip>
<RectangleGeometry Rect="0,0,100,100" />
</Border.Clip>
<ItemsControl ItemsSource="{StaticResource Collection}">
<ItemsControl.RenderTransform>
<TranslateTransform x:Name="Transform" />
</ItemsControl.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:ControlStoryboardAction
Storyboard="{StaticResource TransformMove}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ItemsControl>
</Border>
Then include this Storyboard in your control resources:
<Storyboard x:Key="TransformMove" Storyboard.TargetName="Transform" Storyboard.TargetProperty="Y">
<DoubleAnimation From="-100" To="100" Duration="0:0:10"
RepeatBehavior="Forever"/>
</Storyboard>

Categories