XAML Grid Visibility Transition? - xaml

I have a Grid that has Visibility bound to a property in my viewmodel. This all works fine -- the Grid appears/disappears correctly. My question is, how can I apply a transition so that instead of just instantly disappearing from the screen, the grid content slides into the edge of the UI? When made visible it should slide back out again.
<Grid Grid.Row="0" Grid.RowSpan="2"
Grid.Column="0"
Margin="30,30,0,30"
Visibility="{Binding IsSearchEnabled, Converter={StaticResource visibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
...

So as a quick example, one way of doing this;
<Grid Grid.RowSpan="2" x:Name="TheGrid"
Margin="30,30,0,30"
Visibility="{Binding IsSearchEnabled, Converter={StaticResource visibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Start the magic -->
<Grid.RenderTransform>
<TranslateTransform x:Name="SlideIn" X="750" />
</Grid.RenderTransform>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SlideIn" Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:1.25" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="TheGrid" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0:0:1.55" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
</Grid>
This will slide it in when it's loaded and even fade in as it goes. You might have to play with the "X" value on SlideIn to get it off the screen to your liking. You could reverse it for the other direction.
Hope this helps.

Related

How to style a scrollbar to set it's colour and stop it fading out

I am working on a WinRT application and I have a problem with a scrollbar that needs to be made more noticeable on a white background, and needs to stop disappearing.
The user is meant to answer a number of questions displayed by the listview and at present can easily miss that there are more questions off the end of the screen.
So I would like to style my scrollbars accordingly.
What I find out as a newcomer to XAML is that the solutions I have found online involve a huge amount of code and it is hard to work out from that the very simple things that I want to do.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<TextBlock Text="*" FontSize="40" FontWeight="Bold" Foreground="Red"/>
<TextBlock Text=" = Required " FontSize="20"/>
</StackPanel>
<ListView Grid.Row="1"
ItemsSource="{Binding Path=Survey.SelectedSection.Questions, Mode=TwoWay}"
IsSwipeEnabled="False"
SelectionMode="None"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Background="White"
ItemTemplateSelector="{StaticResource ResourceKey=QuestionDisplay}"
ItemContainerStyle=
"{StaticResource ResourceKey=QuestionListViewItemContainerStyle}" />
</Grid>
So how do I set the colour of the scrollbars and stop them from fading out?
I found that I can get the default styles from here: https://msdn.microsoft.com/library/windows/apps/jj710190.aspx
To put my own colours in I just changed the SolidColorBrush elements. And to stop the scrollbar disappearing I commented out;
<VisualState x:Name="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation BeginTime="0" TargetName="HorizontalPanningRoot" />
<FadeOutThemeAnimation BeginTime="0" TargetName="VerticalPanningRoot" />
<FadeOutThemeAnimation BeginTime="0" TargetName="HorizontalRoot" />
<FadeOutThemeAnimation BeginTime="0" TargetName="VerticalRoot" />
</Storyboard>
</VisualState>

UWP Visual State Manager doesn't see content of DataTemplate

My page structure is shown below.
<ScrollViewer VerticalScrollBarVisibility="Auto">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1"/>
</VisualState.StateTriggers>
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="800"/>
</VisualState.StateTriggers>
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Pivot x:Name="PivotPlatform" Margin="0" ItemsSource="{Binding PivotItems}" Grid.Row="2">
<Pivot.HeaderTemplate>
<DataTemplate>
<StackPanel Height="0" Width="0">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate>
<Grid xmlns:uwp="using:AmazingPullToRefresh.Controls">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<uwp:PullToRefreshAdorner.Extender>
<uwp:PullToRefreshExtender RefreshRequested="PullToRefreshExtender_RefreshRequested" />
</uwp:PullToRefreshAdorner.Extender>
<RelativePanel x:Name="contentPanel" Grid.Row="0" Margin="10 -30 10 10">
<TextBlock Name="titleTB" Text="{Binding Title}" FontSize="12"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignTopWithPanel="True"/>
<TextBlock Name="totalTB" Text="{Binding Total}" FontSize="18"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.Below="titleTB" />
<ProgressBar Name="progressBar" Value="{Binding ProgressValue}" Width="100" Foreground="{StaticResource currentThemeColor}"
RelativePanel.AlignLeftWithPanel="True" RelativePanel.Below="totalTB"
Margin="0 5 0 0"/>
<TextBlock Name="dateTB" Text="{Binding Date}" FontSize="16"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True" />
</RelativePanel>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<Charting:Chart Grid.Row="1" x:Name="LineChart"
Margin="10" >
<Charting:LineSeries Title="" IndependentValuePath="Name" DependentValuePath="Amount"
IsSelectionEnabled="False" ItemsSource="{Binding Result}" />
</Charting:Chart>
</ScrollViewer>
</Grid>
</DataTemplate>
</Pivot.ItemTemplate>
</Pivot>
When I add setter for dateTB textblock into VisualState.Setters to move it to left side of Relative Panel, I get an error saying:
An animation is trying to modify an object named 'dateTB', but no such object can be found in the Page.
Code for adding the setter is:
<Setter Target="dateTB.(RelativePanel.AlignLeftWithPanel)" Value="True"/>
Is there a way to control this textblock through Visual State Manager with this page structure?
It's a problem of name scopes, common to all XAML UI frameworks. Your VSM is in the name scope of your UserControl or Page and the TextBlock is in a DataTemplate.
Romasz's solution to your problem to put the VSM inside of the DataTemplate puts everything you need in a single name scope and is the best solution to this problem.

How to correctly scale view

I'm wondering what is the best way to correcly scale a view in Windows 10 / Windows 8(.1) application.
ViewBox ?
VisualStateManager ?
Other ?
My picture are already suffixed by .scale-xxx.png
In 1366x768, I have :
And in WXGA, I have :
Here is my xaml code :
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="2*" />
<RowDefinition Height="6*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<TextBlock Text="{x:Bind ViewModel.Player, Mode=OneWay}" Margin="20,0,0,0" VerticalAlignment="Center" />
<Image Grid.Row="0" Source="ms-appx:///Resources/Title/title-app.png" VerticalAlignment="Center" Stretch="None" HorizontalAlignment="Center" />
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="10,5,25,5">
<Image Source="ms-appx:///Resources/Rating/star-full.png" Stretch="None" />
<TextBlock FontWeight="Bold" Margin="5,5,0,0" Text="{x:Bind ViewModel.Stars, Mode=OneWay}" FontSize="30" VerticalAlignment="Center" />
</StackPanel>
In my opinion it's the VisualStateManager because here you can find the
AdaptiveTrigger with MaxWindowWidth or MinWindowWidth. Then the diffrent VisulaStates will work perfectly.
For Example:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Width1250">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1310"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Button1.Visibility" Value="Visible"/>
<Setter Target="Button2.Visibility" Value="Visible"/>
<Setter Target="Button3.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
Hope to help you :)
As blueeyes said you can achieve this using visual states. If you don't want to change design you can simply use viewbox to fit the resolution (with stretching).

Why won't Grid rows with height Auto resize with scale-transformed content?

Given the following code, I would have expected the red and green boxes to end up next to eachother, but as you can see in the screenshot of the result, they do not. Instead, the grid rows are sized to accommodate their full size, even though there is a render transform that scales them to half their height.
Is there a way to make the grid rows actually resize themselves and adjust to their contents?
I want this because I couldn't animate the heights of the rows, so I want to animate the heights of their contents instead.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Height="300"
Grid.Row="0"
Background="Red">
<Border.RenderTransform>
<ScaleTransform ScaleY="0.5" />
</Border.RenderTransform>
</Border>
<Border Height="200"
Grid.Row="1"
Background="Green">
<Border.RenderTransform>
<ScaleTransform ScaleY=".5" />
</Border.RenderTransform>
</Border>
</Grid>
As Sheridan says, a RenderTransform is just moving stuff around - independent of other elements. The neat thing is that it's fully hardware accelerated.
To have the system perform animations AND affect layout is a bit more tricky. You probably want to aim for not doing a pure resize, but instead use render transforms to have one element move on top of another, hence hiding it.
But, if you really do want a true resize of content, here's a way to do it.
First, I've added a row with height * at the bottom to allow your Auto rows to just use the size they need.
Secondly, I've created an animation (using Blend of course :) ) - and named the key frames in it, to be able to access them from code behind.
Lastly I modify the animation in the .cs file, and run the animation - voila! Note, this will not be hardware accelerated, but should work for simple UIs.
Code can also be found at: https://github.com/andyhammar/Wp81ResizeRowsTestApp
.xaml
<Page.Resources>
<Storyboard x:Name="AnimateRed">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="_redBorder">
<EasingDoubleKeyFrame KeyTime="0" x:Name="redAnimationFromKeyFrame" Value="300"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" x:Name="redAnimationToKeyFrame" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border
x:Name="_redBorder"
Height="300"
Grid.Row="0"
Background="Red">
</Border>
<Border
x:Name="_greenBorder"
Height="200"
Grid.Row="1"
Background="Green">
</Border>
<StackPanel
Grid.Row="2"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="redSmallButton"
Content="red small"
Click="RedSmallButton_OnClick"/>
<Button
x:Name="redLargeButton"
Content="red large"
Click="RedLargeButton_OnClick"/>
</StackPanel>
</Grid>
.xaml.cs
private void RedSmallButton_OnClick(object sender, RoutedEventArgs e)
{
redAnimationFromKeyFrame.Value = 300;
redAnimationToKeyFrame.Value = 200;
AnimateRed.Begin();
}
private void RedLargeButton_OnClick(object sender, RoutedEventArgs e)
{
redAnimationFromKeyFrame.Value = 200;
redAnimationToKeyFrame.Value = 300;
AnimateRed.Begin();
}
They do, but I'd suggest that you use the LayoutTransform Property instead. The difference is that LayoutTransform is performed before the Arrange and Measure methods are called, so the new size is taken into consideration and RenderTransform is performed afterwards, so it ignores any dimension changes.
You can find a full explanation of the differences in the LayoutTransform vs. RenderTransform - What's the Difference? page on the Scott Logic website.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Height="300"
Grid.Row="0"
Background="Red">
<Border.LayoutTransform>
<ScaleTransform ScaleY="0.5" />
</Border.LayoutTransform>
</Border>
<Border Height="200"
Grid.Row="1"
Background="Green">
<Border.LayoutTransform>
<ScaleTransform ScaleY=".5" />
</Border.LayoutTransform>
</Border>
</Grid>

Windows 8 WebView

I have ran into problem, that WebVie is always on top, i have LoadingGrid (black background with image on it) it haz Z.Index =5.
First thing i show Loading screen, and when WebView finishes loading i hide Loading screen and fade in WebView.
But the problem is that WebView even with Opacity set to 0 - IS VISIBLE! And on top of my loading screen - is there a workaround? Because the only way i found to make WebView invisible set to collapsed - but then my effect doesn't have any reason...
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ShowHideWebView">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="HideWebView"/>
<VisualState x:Name="ShowWebView">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="wv1" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="18*"/>
</Grid.RowDefinitions>
<!--
<Button x:Name="bBack" BorderThickness="0" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Stretch" Click="bBackClick" >
<Button.Background>
<ImageBrush ImageSource="Assets/back_button.png" Stretch="UniformToFill"/>
</Button.Background>
</Button> -->
<WebView x:Name="wv1" HorizontalAlignment="Stretch" Visibility="Collapsed" Grid.Row="1" VerticalAlignment="Stretch" LoadCompleted="wv1_LoadCompleted" Opacity="0" />
<Image HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0" Source="Assets/back_button.png" Tapped="backClick" />
<Grid x:Name="LoadingScreen" Grid.Row="1" Visibility="Collapsed" Canvas.ZIndex="5">
<Grid.Background>
<SolidColorBrush Color="Black" Opacity="0.5"/>
</Grid.Background>
<Image Height="100" Width="100" Opacity="0.5" Source="Assets/loading.gif" Stretch="Fill">
<Image.RenderTransform>
<RotateTransform x:Name="SpinningRotateTransform" CenterX="50" CenterY="50" />
</Image.RenderTransform>
</Image>
</Grid>
</Grid>
You have to stick to Visibility property because when opacity is 0 at that time WebView would be part of visual tree and hence it will be on top of each element. While if it's collapsed it's no longer part of visual tree. I would recommend to try WebViewBrush to show fade effect. When effect is over show WebView.