Rotating a visible set of elements in WPF - c#

This is more for advertising deals to potential customers so there is no human interaction component to this.
Right now I just have the elements bound to an ItemsControl and a storyboard animation loops through. Unfortunately I want to show 4 items at a time, pause on them for 10 seconds, then show the next 4. I could have 5 coupons, I could have 30, so I can't enter anything in statically except that I know my visible width (they will be rotating horizontally) is 1920px.
My current implementation, which displays 1 to 4 then 5 to 8 and loops back to "1" is:
<ItemsControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding Path=VisibleDigitalCoupons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Storyboard x:Key="RotateDigitalCoupons" BeginTime="0:0:0" Duration="0:0:10" RepeatBehavior="Forever" Completed="RotateDigitalCouponsCompleted">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)" Storyboard.TargetName="digitalCouponView">
<EasingDoubleKeyFrame KeyTime="0:0:5" Value="0"></EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:10" Value="-1920">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseInOut"></CubicEase>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<views:DigitalCouponView x:Name="digitalCouponView" Margin="40,40,20,20" Height="240" Width="420" RenderTransformOrigin="0.5,0.5" >
<views:DigitalCouponView.RenderTransform>
<TransformGroup>
<TranslateTransform/>
</TransformGroup>
</views:DigitalCouponView.RenderTransform>
</views:DigitalCouponView>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard x:Name="RotateDigitalCoupons_BeginStoryboard" Storyboard="{StaticResource RotateDigitalCoupons}"/>
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Attempts to use the Completed event to fire off a refresh of the "visible coupons" and reuse the animation have met with failure because the animation is on repeatbehavior forever. However, even with that off, I don't get completed event firing, so that's a dead end AFAIK.
Anyone have any ideas or dealt with this before? Is my process flawed somehow?

Create a Dispatch Timer which contains a state machine which will execute the logic depending on the current state and handle the data driven components of what will be displayed. Within the timer turn on and off the animations as required.
You will need to make the animations more generic of course, but you have the framework which can be leveraged by the timer.

Related

Rotate image inside a button UWP

I'm trying to rotate a font icon inside a button 90° in the first click and back to 0° on the second click.
Currently I have:
<Page.Resources>
<Storyboard x:Name="RotateButton90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="350" />
</Storyboard>
</Page.Resources>
<Button
x:Name="ShowSubTasks_Button"
Background="Transparent">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButton90Degrees}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
The problem is that the app crashes when I click the button (it's not finding the ShowSubTasks_ButtonRotateTransform). The second is that I don't know how to revert the rotation effect after the first click (first click -> 90°, second click -> 0°, third click -> 90° and so on).
Any help would be appreciated.
Ok i got the problem, the thing is that im running all that code inside a DataTemplate ... So that explains why its crashing. For the fix i used what #Dishant suggested, created two storyboards and with a DataTriggerBehavior i change the angle of the rotate transform
<StackPanel.Resources>
<Storyboard x:Name="RotateButtonTo90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Name="RotateButtonTo0Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="90"
To="0"
Duration="0:0:0.1" />
</Storyboard>
</StackPanel.Resources>
<Button
Background="Transparent"
Visibility="{Binding HasSubTasks, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="True">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo90Degrees}" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="False">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo0Degrees}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
Also as #MartinZikmund suggested, i needed to change the duration from 350 to something like 0:0:0.5
In my case the app does not crash, but the icon does not rotate, because the duration is set to 350, which basically means 350 hours. If you change this value to something like 0:0:0.5, it should rotate in 0.5 seconds. To do the reverse animation, you would probably need to set the animation target programatically, but in such case you could just run the storyboard itself in the Click event handler.
If you are targeting Windows 10 15063 or higher, you can use Implicit Animations in XAML. In that case you could set up an implicit animation on the rotation of the icon and then just set the rotation property in the code-behind accordingly and implicit animation would take care of the animation itself.

Acrobat-like PopUp in WPF

Im recently working on some simple Imageviewer.
Now it came to my mind, it might be a nice feature, to do some context-sensitve actions like Zooming and rotating.
To implement these functions is not my problem, but the ContextMenu is.
I've decided to not use a ContextMenu-Element, instead im going to use a popup.
Reasons for PopUp:
Less Styling
Better Positioning
IsOpen is Bindable (ContextMenu is NOT bindable on IsOpen against all Articles regarding this)
Here comes the trouble:
<Image x:Name="PART_ImgCurrent" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" Grid.Row="0" Grid.Column="0"
Source="{Binding ElementName=PART_PreviewPanel, Path=SelectedItem.Source}">
<Image.LayoutTransform>
<RotateTransform Angle="0"></RotateTransform>
</Image.LayoutTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_ImgCurrent" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
<Popup IsHitTestVisible="False" Focusable="False" PlacementTarget="{Binding ElementName=PART_ImgCurrent}" AllowsTransparency="True" StaysOpen="True"
IsOpen="{Binding ElementName=PART_ImgCurrent, Path=IsMouseOver, Mode=OneWay}"
Placement="Right" HorizontalOffset="-42" VerticalOffset="2">
<StackPanel Opacity="0.5" VerticalAlignment="Stretch">
<Button Content="Ugly Button" Height="40" Width="40"></Button>
<Button Content="Ugly Button" Height="40" Width="40"></Button>
<Button Content="Ugly Button" Height="40" Width="40"></Button>
</StackPanel>
</Popup>
As you can see, im binding IsOpen of Popup to IsMouseOver on Image which results in a funny Disco-BlinkenLights-Behavior when i try to click a button inside the Popup.
What has this to do with the Title?
AcrobatReader has this
This is almost exactly the behavior im looking for. How is this thing called?
Or had someone ever similar issues and could provide a solution?
Sorry for the delay, soon as I thought I had a second I got busy again. Anyway, here's one of several ways I can think of accomplishing your goal, give it a shot. I sort of assumed it may not be just images you want this for and if you threw the resource stuff in a dictionary and kept your naming consistent (or even better, just target the nested UIElement) you could use it all over the place. Notice the Grid is acting as what would be the Image in this example.
I generally make things open for future added interactions and stuff, so in this case I would probably just make the image source the background brush for Grid or place it as a child. That way if you decide to add other objects in there or say other effects and stuff you've got a good start point.
Anyway I digress, so try out the concept example below and see if it's what you're after. If not, like I said there's several other ways I can think of to accomplish your goal so just let me know. :)
<!-- HitTestVisibility Area -->
<Grid x:Name="ImagePlaceholder"
Height="500" Width="500"
Background="LightBlue">
<Grid.Resources>
<Storyboard x:Key="OnMouseEnter">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="FakePopUp">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnMouseLeave">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="FakePopUp">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource OnMouseEnter}"/>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource OnMouseLeave}"/>
</EventTrigger>
</Grid.Triggers>
<!-- Overlay -->
<Border Name="FakePopUp" Visibility="Collapsed"
Margin="0,0,0,25" Background="SlateGray"
Height="50" CornerRadius="20" Padding="10"
HorizontalAlignment="Center" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal">
<Button Content="Eins Bier"/>
<Button Content="Zwei Bier" Margin="10,0"/>
<Button Content="Drei Bier"/>
</StackPanel>
</Border>
</Grid>
I went with Storyboards attached to the parent instead of direct triggers with TargetName like I said, because I could think of a bunch of other instances features might want to be added that would make sense. Even something simple like adding a transition duration for a nice fade effect or maybe a translate y to slide it up while fading etc, etc, etc.
Anyway, hope this helps. Cheers!

FlipView EventTrigger for the SelectionChanged event

I'm developing universal app. On one page i decided to use FlipView. I can easily animate SelectionChanged event from code-behind, but i'm just curious if there is a way to animate this event using XAML only. (BTW, UseTouchAnimationsForAllNavigation="True" doesnt work).
So, here's simplified example of what i'm doing :
<FlipView x:Name="MultipleItems">
<FlipView.Triggers>
<EventTrigger RoutedEvent="Selector.SelectionChanged">
<BeginStoryboard>
<Storyboard x:Name="ColorStoryboard">
//do stuff
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<FlipView.Triggers>
</FlipView>
I think this way of usage EventTrigger is fine (as far as SelectionChanged event takes arguments inherited from RoutedEventArgs), but it still gives me runtime error on navigation to page that contains FlipView.
Error is next :
WinRT information: Failed to assign to property 'Windows.UI.Xaml.EventTrigger.RoutedEvent'. [Line: 69 Position: 35]
Additional information: The text associated with this error code could not be found.
I believe there's way to assign that RoutedEvent property correctly, but i didnt find it yet. Also I don't wont to use behaviours for such simple thing.
Can anyone help?
You need to install the Microsoft.Xaml.Behaviors.Uwp.Managed in your project. Then the EventTrigger will be supported in an UWP project.
Then in your XAML use this package like this:
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
Now you can for example change the background color of FlipView like this:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<Storyboard x:Key="std" x:Name="std" >
<ColorAnimation From="Red" To="Transparent" Duration="0:0:3"
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Storyboard.TargetName="flipView"/>
</Storyboard>
</Grid.Resources>
<FlipView x:Name="flipView" ItemsSource="{x:Bind flipviewCollection}">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Media:ControlStoryboardAction Storyboard="{StaticResource std}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<FlipView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageSource}" Stretch="None"/>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Grid>
As you can see, I used EventTriggerBehavior and the event's name is SelectionChanged.

Event for a Storyboard repeatedly in WP8

I wrote a storyboard which make a ball (imgBall) running repeatedly on a process bar (imgBar) - with repeat behavior = "forever", but I don't see event which occur when single turn start or end, It only have Completed event (which occur when the whole storyboard finished)
<Grid Margin="20,0,0,0">
<Canvas Canvas.ZIndex="1" >
<Canvas.Resources>
<Storyboard x:Name="myStoryboard" Completed="myStoryboard_Completed">
<!-- Animate the center point of the ellipse. -->
<DoubleAnimation Storyboard.TargetName="imgBall"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
Duration="0:0:2"
From="10" To="350"
RepeatBehavior="Forever"
></DoubleAnimation>
</Storyboard>
</Canvas.Resources>
<Image Source="/Assets/Image/processball.png" x:Name="imgBall">
<Image.RenderTransform>
<CompositeTransform TranslateX="10" TranslateY="2"/>
</Image.RenderTransform>
</Image>
</Canvas>
<Image Source="/Assets/Image/imgBar.png"/>
</Grid>
</StackPanel>
You can remove RepeatBehavior="Forever" and repeat your Storyboard from code behind in Completed event Handler using .Begin() method.

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

Categories