I have a scenario where I have to generate create same StoryBoard Animation in Xaml for a set of data(which I will bind form ViewModel).
<Page
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
xmlns:miControls="using:Microsoft.UI.Xaml.Controls">
<Page.Resources>
<miControls:ItemsRepeater x:Name="repmeaterTest">
<miControls:ItemsRepeater.ItemTemplate>
<DataTemplate>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetName="DemoCircle" Storyboard.TargetProperty="(FrameworkElement.Width)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="50"/>
<EasingDoubleKeyFrame KeyTime="00:00:04" Value="250"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetName="DemoCircle" Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="50"/>
<EasingDoubleKeyFrame KeyTime="00:00:04" Value="250"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate>
</miControls:ItemsRepeater.ItemTemplate>
</miControls:ItemsRepeater>
</Page.Resources>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="clikToAnimate" Content="Animate" Click="clikToAnimate_Click" Margin="10"/>
<Ellipse Name="DemoCircle" Stroke="Purple" Width="50" Height="50" StrokeThickness="4" Fill="AntiqueWhite"/>
</StackPanel>
public sealed partial class MainPage : Page
{
List<int> noOfStoryBoard = new List<int> { 1,2,3,4,5};
public MainPage()
{
this.InitializeComponent();
}
private void clikToAnimate_Click(object sender, RoutedEventArgs e)
{
Storyboard1.Begin();
}
}
I want to generate StoryBoard dynamically for noOfStoryBoard(ie 5) in xaml
Does anyone have idea kindly share,
Here what i have tried to use items repeater
I am having Storyboard in my Page resources to share it between required controls. I try to animate clicked ListItem using that Storyboard in code behind by setting TargetName propery.
<Page.Resources>
<Storyboard x:Name="Story1">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="-200"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<ListView x:Name="ListView1" IsItemClickEnabled="True" ItemClick="ListView1_ItemClick">
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="GridData">
<Grid.RenderTransform>
<TranslateTransform x:Name="GridTrans" X="0" />
</Grid.RenderTransform>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Price}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
{
Story1.Stop();
var item = ListView1.ContainerFromItem(e.ClickedItem) as ListViewItem;
var grid = item.ContentTemplateRoot as Grid;
Storyboard.SetTargetName(Story1, grid.Name); //???
Story1.Begin();
}
But unable to animate clicked ListItem on ItemClick event. I get error as "Cannot resolve TargetName GridData"
The GridData is under DataTemplate, if you use SetTargetName method to set animation, it will not get correct ContentTemplateRoot. For your requirement, you could use SetTarget method.
private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
{
Story1.Stop();
var item = ListView1.ContainerFromItem(e.ClickedItem) as ListViewItem;
var grid = item.ContentTemplateRoot as Grid;
Storyboard.SetTarget(Story1, grid);
Story1.Begin();
}
The request is that the row of my ListView blinks when the property SelectedItem of the ViewModel raises change.
This is my code, the problem is that it works only first time. Subsequent changes are ignored.
<DataTemplate x:Key="myDataTemplate">
<Grid x:Name="myGrid">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding SelectedItem}" Value="True">
<Media:ControlStoryboardAction>
<Media:ControlStoryboardAction.Storyboard>
<Storyboard>
<ColorAnimation
To="#009ABF"
Storyboard.TargetName="myGrid"
Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)"
AutoReverse="True"
Duration="0:0:1"
RepeatBehavior="1x" />
</Storyboard>
</Media:ControlStoryboardAction.Storyboard>
</Media:ControlStoryboardAction>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<TextBlock Text="{Binding Name}"
Grid.Column="1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="0,2,10,0"
FontSize="16"
TextAlignment="Left"/>
<!--OMISSIS-->
</Grid>
SelectedItem code :
public bool SelectedItem
{
get
{
return this.selectedItem;
}
set
{
this.selectedItem = value;
this.RaisePropertyChanged();
}
}
This is the solution i found.
1) Use Completed event of the Storyboard
<Storyboard Completed="SelectedItemReset" FillBehavior="Stop">
3) Use the GalaSoft.MvvmLight.Messaging.Messenger to comunicate from CodeBehind and ViewModel the reset of the property SelectedItem
Xaml
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="DataTemplateGrid">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding SelectedItem}" ComparisonCondition="Equal" Value="True">
<Media:ControlStoryboardAction ControlStoryboardOption="Play">
<Media:ControlStoryboardAction.Storyboard>
<Storyboard Completed="SelectedItemReset" FillBehavior="Stop">
<ColorAnimation
To="Lime"
Storyboard.TargetName="DataTemplateGrid"
Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)"
Duration="0:0:1"/>
</Storyboard>
</Media:ControlStoryboardAction.Storyboard>
</Media:ControlStoryboardAction>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<!--OMISSIS-->
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
CodeBehind
private void SelectedItemReset(object sender, object e)
{
GalaSoft.MvvmLight.Messaging.Messenger.Default.Send<Mvvm.ViewModels.Units.SelectedItemResetMessage>(new Mvvm.ViewModels.Units.SelectedItemResetMessage());
}
MVVM Class .ctor
public MyViewModel()
{
GalaSoft.MvvmLight.Messaging.Messenger.Default.Register<SelectedItemResetMessage>(this, message =>
{
if (this.SelectedItem == true)
this.SelectedItem = false;
});
}
Note: My DataTemplate was in a separate file and linked to the ListView with the ItemTemplate property, this prevented me from calling the method Completed in CodeBehind.
I want to animate input box just like the one above how to do it in MVVM template 10
I have a list view
and need the search bar just like the image
I have attached an solution to your problem. There are two storyboards that are triggered on GotFocus and Lost Focus for an AutoSuggestBox in UWP c#
Here us what I achieved:
XAML :
<Page.Resources>
<Storyboard x:Name="OnCancel">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="70">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="HeaderGrid">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="51"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="HeaderGrid">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="HeaderGrid">
<EasingDoubleKeyFrame KeyTime="0" Value="-36.058"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="OnTextBoxFocus">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="70">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="HeaderGrid">
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Duration="0:0:0.4" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="HeaderGrid" d:IsOptimized="True"/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="HeaderGrid">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="-36.058"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="HeaderGrid" Margin="0,0,-1,-0.117" RenderTransformOrigin="0.5,0.5" Height="51">
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="TextBlock" Margin="5,0,1,3" FontSize="36" SelectionHighlightColor="{x:Null}" Foreground="DodgerBlue"/>
<TextBox Width="1" Height="1" IsReadOnly="True"/>
<Path Data="M0,48 L360,48" Height="1" Margin="0,0,0,0.117" Stretch="Fill" Stroke="DodgerBlue" UseLayoutRounding="False" VerticalAlignment="Bottom" d:LayoutOverrides="LeftPosition, RightPosition"/>
</Grid>
<StackPanel Grid.Row="1">
<Grid Height="32" Margin="12,8,12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<AutoSuggestBox x:Name="searchText" PlaceholderText="Search" QueryIcon="Find" TextMemberPath="name" LostFocus="searchText_LostFocus" GotFocus="searchText_GotFocus"/>
<Button x:Name="button" Content="Cancel" VerticalAlignment="Stretch" d:LayoutOverrides="Height" Grid.Column="4" Margin="5,0,0,0" Width="70" Click="button_Click"/>
</Grid>
<ListView x:Name="listView" Background="#FFECECEC" Margin="0,8,0,0">
<ListViewItem Content="List View Item 1" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 2" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 3" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 4" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 5" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 6" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 7" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 8" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 9" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
<ListViewItem Content="List View Item 10" BorderThickness="0,0,0,1" BorderBrush="#FFB9B9B9"/>
</ListView>
</StackPanel>
</Grid>
and in code behind XAML.CS
private void searchText_LostFocus(object sender, RoutedEventArgs e)
{
OnCancel.Begin();
}
private void button_Click(object sender, RoutedEventArgs e)
{
OnCancel.Begin();
}
private void searchText_GotFocus(object sender, RoutedEventArgs e)
{
OnTextBoxFocus.Begin();
}
Also dont forget to set width of button = 0 on Initialization.
Hope this helps.
You can use data binding to bind your title and Cancel button's Visibility property to property defined in your ViewModel, as #Raunaq Patel said, the animations are triggered by GotFocus and LostFocus event.
So you can for example code like this:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="pageHeader" Text="Main Page" Grid.Row="0" Visibility="{Binding IsVisible}" FontSize="30" />
<Grid Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<AutoSuggestBox HorizontalAlignment="Stretch" GotFocus="{x:Bind ViewModel.Search_GotFocus}"
LostFocus="{x:Bind ViewModel.Search_LostFocus}" VerticalAlignment="Stretch"
Width="{Binding BoxWidth}" />
<TextBlock Text="Cancel" Foreground="BlueViolet" Tapped="{x:Bind ViewModel.Cancel_Tapped}" Width="100"
VerticalAlignment="Stretch" HorizontalAlignment="Center" FontSize="20"
Visibility="{Binding CancelIsVisible}" Grid.Column="1" />
</Grid>
<ListView Grid.Row="1" IsEnabled="{Binding ListViewEnable}">
<ListViewItem>Item 1</ListViewItem>
<ListViewItem>Item 2</ListViewItem>
<ListViewItem>Item 3</ListViewItem>
<ListViewItem>Item 4</ListViewItem>
<ListViewItem>Item 5</ListViewItem>
</ListView>
</Grid>
</Grid>
Since you are using Template 10, code behind is for example in the MainPageViewModel like this:
public class MainPageViewModel : ViewModelBase
{
private Visibility _IsVisible;
public Visibility IsVisible
{
get { return _IsVisible; }
set
{
if (value != _IsVisible)
{
_IsVisible = value;
RaisePropertyChanged();
}
}
}
private Visibility _CancelIsVisible;
public Visibility CancelIsVisible
{
get { return _CancelIsVisible; }
set
{
if (value != _CancelIsVisible)
{
_CancelIsVisible = value;
RaisePropertyChanged();
}
}
}
private bool _ListViewEnable;
public bool ListViewEnable
{
get { return _ListViewEnable; }
set
{
if (value != _ListViewEnable)
{
_ListViewEnable = value;
RaisePropertyChanged();
}
}
}
private double _BoxWidth;
public double BoxWidth
{
get { return _BoxWidth; }
set
{
if (value != _BoxWidth)
{
_BoxWidth = value;
RaisePropertyChanged();
}
}
}
public MainPageViewModel()
{
_IsVisible = Visibility.Visible;
_CancelIsVisible = Visibility.Collapsed;
_ListViewEnable = true;
_BoxWidth = Window.Current.Bounds.Width;
}
public void Search_GotFocus(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
IsVisible = Visibility.Collapsed;
CancelIsVisible = Visibility.Visible;
ListViewEnable = false;
BoxWidth = _BoxWidth - 100;
}
public void Search_LostFocus(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
IsVisible = Visibility.Visible;
CancelIsVisible = Visibility.Collapsed;
ListViewEnable = true;
BoxWidth = Window.Current.Bounds.Width;
}
public void Cancel_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
IsVisible = Visibility.Visible;
CancelIsVisible = Visibility.Collapsed;
ListViewEnable = true;
BoxWidth = Window.Current.Bounds.Width;
}
}
Here you can see the data in ListView are fake, you can of course use DataTemplate and bind collection to the ItemSource of the ListView. Here is the rendering image of my sample:
It's AutoSuggestBox.
You can see how to use in https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlAutoSuggestBox
And you can see summary on https://msdn.microsoft.com/zh-cn/windows/uwp/controls-and-patterns/auto-suggest-box?f=255&MSPPError=-2147217396
I would like to add a hover effect to the border that I've created as below.
<Border x:Name="borderHeader" Background="#000000" Height="100" VerticalAlignment="top" Opacity="0.5" HorizontalAlignment="Left" Width="1366">
And my visual state code as below.
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="borderHeader"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
How ever it's not working.
Please advise which part I have did wrongly.
Thanks
Visual states can be applied to those controls which are inside ControlTemplate. Border is stand alone control. So you need to rely on PointerEntered & PointerExited events.
XAML
<Border x:Name="borderHeader" Background="Yellow" Height="100" VerticalAlignment="top" Opacity="0.5" HorizontalAlignment="Left" Width="1366"
PointerEntered="borderHeader_PointerEntered_1" PointerExited="borderHeader_PointerExited_1"/>
C#
private void borderHeader_PointerEntered_1(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
borderHeader.Opacity = 1;
}
private void borderHeader_PointerExited_1(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
borderHeader.Opacity = 0.5;
}