How to animate HubSection when visibility changed in WinRT Hub Control - xaml

I have a HubSection that is dynamically shown/hidden using Visibility Collapsed/Visible during runtime. I would like to animate the HubSection by having it expand and shrink instead of just instantly showing or hiding it.
Animations in WinRT tend to be a science, and I haven't found a good method yet.
If someone could help with a code snippet I would appreciate it. I would prefer to keep it to XAML if possible, rather than putting the animation in a code-behind. Thanks!

Assuming that the visibiity of the hubsection is controlled by a boolean property of a viewmodel, bound through a converter then the solution is simpler than I thought. Even if this is not the case I'm sure you can modify the solution below easily.
You will need to reference the Behaviors SDK for this to work. You can do that either by going to References>Add Reference>Windows 8.1>Extensions>Behaviors SDK or by opening your project in blend and dragging a DataTriggerBehavior on yor hubsection.
Necessary xmlns declarations
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
<Page.Resources>
<Converters:BoolToVisConverter x:Key="BoolToVisConverter"/>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="hubSection">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="400"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Hub Header="Hub">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior/>
</Interactivity:Interaction.Behaviors>
<HubSection Header="HubSection 0">
<DataTemplate>
<Grid/>
</DataTemplate>
</HubSection>
<HubSection x:Name="hubSection" Header="HubSection 1" Visibility="{Binding MyProperty, Converter={StaticResource BoolToVisConverter}}" Width="400" Background="#FFB02626">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding MyProperty}" Value="True">
<Media:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<DataTemplate>
<Grid/>
</DataTemplate>
</HubSection>
</Hub>
<ToggleSwitch Header="ToggleSwitch" HorizontalAlignment="Left" Margin="824,249,0,0" VerticalAlignment="Top" IsOn="{Binding MyProperty, Mode=TwoWay}"/>
The xaml defines a hub with 2 hubsections a toggleswitch to manipulate the boolean property in the viewmodel and a storyboard to animate the second hubsection.
The trick is to use a DataTriggerBehavior instead of an EventTriggerBehavior.
You can even bind directly to the visibility property of the hubsection for the DataTriggerBevavior if you want.

Related

Getting a value from a higher databinding path

I have an object that contains a control defined in a control template, and an object which it gets notifications from.
These notification object keeps track of the status of the object, which translates on the screen to the colour in this instance, although they are used in other areas of the UI to reflect the state of these objects.
The rectangle colour changes fine on the status change, but I have another property which provides the foreground colour of the text.
However, because of the ContentPresenter getting the text from the control, I can no longer get the foreground colour with the TextBlock.Foreground setter in the style, as the binding is pointing elsewhere.
I could put the name of the object in the notification object as well which would get rid of this question and problem, but I have run up against a similar issue in other places, and as I am new to WPF would like to know the way to do it.
This is the main relevant part of the ControlTemplate 'AnimatedTemplate':
<Rectangle x:Name="ColourFill" Stroke="White" RadiusX="5" RadiusY="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Path=FillColour}"/>
</Rectangle.Fill>
<Rectangle.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Active}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard> ... </BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="2"
TextBlock.FontFamily="Segoe UI"
TextBlock.FontWeight="Bold">
<ContentPresenter.Style>
<Style>
<Setter Property="TextBlock.FontSize"
Value="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent},
Converter={StaticResource PushPinContentSizeConverter}}" />
<Setter Property="TextBlock.Foreground"
Value="{Binding Path=TextColour}"/>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
this is created with:
ControlTemplate template = (ControlTemplate)_window.FindResource("AnimatedTemplate");
Control c = new ContentControl();
c.Template = template;
c.SetValue(ContentControl.ContentProperty, displayName);
c.DataContext = <the notification object referred to as the first binding>
_window.d1overlay.Children.Add(c);

Storyboard inside datatemplate Windows 8.1

Is it possible to Begin a storyboard from code behind(.cs file) which is inside a datatemplate. The Below code is not working please advice me.
<HubSection Width="800" x:Name="Section2" Header="Section 2" Foreground="Black">
<DataTemplate x:Name="DataTemplateNotificaiton" >
<Grid Background="White" Width="700" Height="500" Margin="-20" >
<Canvas x:Name="canvas" Margin="0,302,0,-302" Canvas.ZIndex="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5" >
<Canvas.Resources>
<Storyboard x:Name="TileAnimation">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="canvas">
<EasingDoubleKeyFrame KeyTime="0" Value="-1.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="-252"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Canvas.Resources>
<Canvas.RenderTransform>
<CompositeTransform/>
</Canvas.RenderTransform>
<TextBlock x:Name="panel1" Margin="30,30,0,0" Text="sdasdasdasd" FontFamily="Segoe WP Light" FontSize="32" >
<TextBlock.RenderTransform>
<TranslateTransform/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock x:Name="panel2" Margin="30,7,0,0" TextWrapping="Wrap" Text="adasdasdasdasd" FontFamily="Segoe WP Light" FontSize="22" Canvas.Top="98">
<TextBlock.RenderTransform>
<TranslateTransform/>
</TextBlock.RenderTransform>
</TextBlock>
</Canvas>
</Grid>
</DataTemplate>
</HubSection>
c# code behind:
Storyboard anim = (Storyboard)FindName("TileAnimation");
anim.Begin();
Yes, but complicated and not recommended, when you want to keep your code readable.
What I recommend is, develop a userControl which contains everything what is currently in your Template, and then design your animations in that control.
You can easily add this new control in the datatemplate instead of the code above. That makes it also easier to test the control.
HTH-Oliver

Setting the GroupStyle.Panel of a ListView on Windows Phone

I'm trying to create a ListView with grouping where the elements in each group are shown horizontally (as a scrollable content). No matter what I tried with the GroupStyle.Panel of the ListView it doesn't seem to have any effect on the list.
Here is how my XAML looks:
<ListView x:Name="itemListView"
Padding="10"
SelectionMode="None"
IsSwipeEnabled="False"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource listItemTemplate}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<ItemsWrapGrid ItemWidth="144" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding DisplayTitle}"
Margin="0,10,0,5"
Foreground="Black"
Style="{StaticResource SubheaderTextBlockStyle}"
TextWrapping="NoWrap" />
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
Where
<Page.Resources>
<DataTemplate x:Key="listItemTemplate">
<Grid Width="144" Margin="5">
<!-- details -->
</Grid>
</DataTemplate>
</Page.Resources>
The following image shows on the left the actual result I get, and on the right what I want to have.
I tried using a ItemsWrapGrid with different properties, I tried a StackPanel and even an VariableSizedWrapGrid, but nothing changed in the way the list items are displayed.
How can this be done?
#kubakista was right about
It looks like if ListView.ItemsPanel contains ItemsStackPanel then
GroupStyle.Panel is ignored...
However, changing this won't solve your problem as -
The scrolling becomes a bit laggy.
There is no horizontal scrolling.
The ListView loses virtualization.
The nice group header rolling up animation is gone.
Here is an alternative without changing the structure of the ListView itself but a little bit modification in your data structure.
The idea is, treat each horizontal list of rectangles under a group as one collection item on the UI.
This means, each group in the ListView will only have one child, which is actually a collection of rectangles that will be presented in an horizontal scrollable ItemsControl.
So, assume you have some collection of type ObservableCollection<Item> as the CollectionViewSource, the Item will now become type of <ObservableCollection<Item>> in order to hold the collection of rectangles. Therefore, the type of the collection will need to be updated to something like ObservableCollection<ObservableCollection<Item>>.
Inside the ListView's ItemTemplate, you will need to create a horizontally scrolling ScrollViewer and put an ItemsControl inside. Make sure you have set the latter's ItemsSource to {Binding}.
To enable horizontal swiping, you will need to disable the tilt effect by editing the default style of ListViewItem and commenting out the following code.
<!--
<VisualStateGroup.Transitions>
<VisualTransition From="Pressed" To="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="TiltContainer"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Pressed">
<Storyboard>
<PointerDownThemeAnimation Storyboard.TargetName="TiltContainer"/>
</Storyboard>
</VisualState>
-->
I have attached a working sample project here as well as a screenshot shown below.
Hope this helps!

Animate an XAML Eclipse for Pushpin control

I'm a bit a of XAML noob so this is probably something very simple I'm missing...
In a Windows Phone 8 app I have a map Pushpin I'm trying to animate with an effect very much like ripples in a pond. I have a large container eclipse and a child eclipse that will expand from 0 width/height to 30 width/height (the same size as the parent eclipse).
I'm doing this to visually indicate to the user that their location is actively being tracked, or just been picked up.
Unfortunately I've not managed to get my animation working.
<ControlTemplate x:Key="UserLocationPushpinControlTemplate" TargetType="m:Pushpin">
<Grid x:Name="ContentGrid" Width="34" Height="34">
<Grid.Resources>
<Storyboard x:Name="Storyboard1">
<DoubleAnimation
Storyboard.TargetName="Animated"
Storyboard.TargetProperty="Width"
From="0" To="30" Duration="0:0:1" AutoReverse="False"
RepeatBehavior="Forever" />
<DoubleAnimation
Storyboard.TargetName="Animated"
Storyboard.TargetProperty="Height"
From="0" To="30" Duration="0:0:1" AutoReverse="False"
RepeatBehavior="Forever" />
</Storyboard>
</Grid.Resources>
<Grid MinHeight="30" MinWidth="30">
<Ellipse x:Name="Parent" Margin="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="30"
Height="30"
Stroke="White"
StrokeThickness="3"
Fill="{StaticResource PrimaryColorBrush}"/>
<Ellipse x:Name="Animated" Margin="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="0"
Height="0"
Stroke="White"
StrokeThickness="2"/>
</Grid>
</Grid>
</ControlTemplate>
Just in case it's relevant - this ControlTemplate is within a UserControl housing my Windows Phone 7 / Bing map control (the Windows Phone 8 map control is lacking some functionality I require).
Any help would be greatly appreciated. Thank you.
Update
I can add an animation, but am not sure how to apply the Storyboard via code. Ideally I'd like to apply the Storyboard by code as I'd like to define a couple for different circumstances.
Here's the updated XAML:
<ControlTemplate x:Key="UserLocationPushpinControlTemplate" TargetType="m:Pushpin">
<Grid x:Name="ContentGrid" Width="34" Height="34">
<Grid.Resources>
<Storyboard x:Name="LocateStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="AnimatedEllipse" RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="30"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="AnimatedEllipse" RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="30"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Grid MinHeight="30" MinWidth="30">
<Ellipse x:Name="ParentEllipse" Margin="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="30"
Height="30"
Stroke="White"
StrokeThickness="3"
Fill="{StaticResource PrimaryColorBrush}"/>
<Ellipse x:Name="AnimatedEllipse" Margin="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="0"
Height="0"
Stroke="White"
StrokeThickness="2"/>
</Grid>
</Grid>
</ControlTemplate>
As a side note: I had issues creating the animation before as I was unaware that Blend does not record changes if you're tweaking the XAML code directly. You need to seek out the various property controls and set everything there.
This is the code I was trying to use to start the animation:
Pushpin pushpin = new Pushpin();
pushpin.Tag = PIN_TAG;
pushpin.Location = ViewModel.Location;
pushpin.Template = (ControlTemplate)Resources["UserLocationPushpinControlTemplate"];
pushpin.PositionOrigin = PositionOrigin.Center;
MapBase.Children.Add(pushpin);
Storyboard animation = (Storyboard)pushpin.Resources["LocateStoryboard"];
animation.Begin();
The storyboard variable is null. It seems I need to delve in to the ControlTemplate structure to dig down to the "LocateStoryboard" resource. Any ideas how to do this?
Not sure if it can help, but take a look at the article by Igor Ralic here... He has a detailed example on how to add a fade in animation on pushpins.

Problem with statemanager in SL4

I have a togglebotton
<ToggleButton Padding="1">
<TextBlock>
<Underline>Week</Underline>
</TextBlock>
</ToggleButton>
and what I need to change is set underline to false, when togglebutton is unchecked, and set it to true, when control is ckecked.
and now I have only
<ToggleButton Padding="1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="IsChecked">
<Storyboard Duration="0:0:0">
and I can't figure out what next .
I'm not stick with conception with textblock. Text in the ToggleButton should be underline and that's all.
In order to use VisualStateManager you would have to redefine the template of the ToggleButton - take a look at the MSDN ToggleButton Syles. Instead of that you can use Blend's triggers. First add to your project System.Windows.Interactivity.dll and Microsoft.Expression.Interactions.dll provided by Expression Blend SDK and then use the following code:
<ToggleButton x:Name="toggleButton" Padding="1">
<TextBlock x:Name="textBlock">
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding IsChecked, ElementName=toggleButton}" Value="True">
<ei:ChangePropertyAction PropertyName="TextDecorations">
<ei:ChangePropertyAction.Value>
<TextDecorationCollection>Underline</TextDecorationCollection>
</ei:ChangePropertyAction.Value>
</ei:ChangePropertyAction>
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding IsChecked, ElementName=toggleButton}" Value="False">
<ei:ChangePropertyAction PropertyName="TextDecorations"/>
</ei:DataTrigger>
</i:Interaction.Triggers>
Week
</TextBlock>
</ToggleButton>
The ei: and i: are the following:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"