I have a grid. which contains a canvas of textblock and an image below it. I want to hide the canvas when user clicks on grid. And if he clicks again on it I want to show the canvas again and vice versa. This expansion and collapse should happens in an animated/sliding way. Which means I want to get an Expander to animate opening and closing with a "slide" action. How can I achieve this?
<Grid x:Name="NotiifcationGrid" Background="#002F43" Height="50" Grid.Row="0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Canvas Grid.Row="0">
<Canvas.Clip>
<RectangleGeometry Rect="0, 0, 1700, 100" />
</Canvas.Clip>
<TextBlock Name="txtScrollingNotification" Foreground="White"
Text="This textblock is getting marquee effect." />
</Canvas>
<Image x:Name="img_greenline" Grid.Row="1" Height="40" Width="80" Source="Assets/green_line.png" />
<Grid.Resources>
<Storyboard x:Name="Storyboard1">
<DoubleAnimation
Storyboard.TargetName="txtScrollingNotification"
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:20" From="1700"
To="-500"
RepeatBehavior="Forever" />
</Storyboard>
</Grid.Resources>
</Grid>
If you just want to animate adding and deleting of content in your Grid, then you should use AddDeleteThemeTransition.
Like this:
<Grid>
<Grid.ChildrenTransition>
<AddDeleteThemeTransition/>
</Grid.ChildrenTransition>
<Canvas..../>
<Image...../>
</Grid>
Also, If you don't like the output and your problem specially need the Expander solution, then you can use the Expander in Community Toolkit.
Hope that helps.
I want to hide the canvas when user clicks on grid. And if he clicks again on it I want to show the canvas again and vice versa. This expansion and collapse should happens in an animated/sliding way.
I've checked your XAML code, using Storyboard was a good choice, but you need to add another storyboard to achieve your target.
I've made a code sample for your reference. Please check the following code sample:
<Grid x:Name="NotiifcationGrid" Background="#002F43" Height="50" Grid.Row="0" VerticalAlignment="Top" Tapped="NotiifcationGrid_Tapped">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Canvas Grid.Row="0" x:Name="canvas">
<Canvas.Clip>
<RectangleGeometry Rect="0, 0, 1700, 100" />
</Canvas.Clip>
<TextBlock Name="txtScrollingNotification" Foreground="White"
Text="This textblock is getting marquee effect."/>
</Canvas>
<Image x:Name="img_greenline" Grid.Row="1" Height="40" Width="80" Source="Assets/green_line.png" />
<Grid.Resources>
<Storyboard x:Name="Storyboard1" Completed="Storyboard1_Completed">
<DoubleAnimation
Storyboard.TargetName="txtScrollingNotification"
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:2" From="0"
To="-500"
/>
</Storyboard>
<Storyboard x:Name="Storyboard2">
<DoubleAnimation
Storyboard.TargetName="txtScrollingNotification"
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:2" From="-500"
To="0"
/>
</Storyboard>
</Grid.Resources>
</Grid>
private void NotiifcationGrid_Tapped(object sender, TappedRoutedEventArgs e)
{
if (canvas.Visibility == Visibility)
{
Storyboard1.Begin();
}
else
{
canvas.Visibility = Visibility;
Storyboard2.Begin();
}
}
private void Storyboard1_Completed(object sender, object e)
{
canvas.Visibility = Visibility.Collapsed;
}
[Updated on 2018/9/3]
sorry this is not what i meant. that canvas shows some notifications. so when user touch on that NotiifcationGrid , he should feel like it is hiding. and again if he touch on it he should able to see those notification row. Now what happens is only that notification text is hiding. I want to hide that entire row Grid.Row="0" (should feel like hide from bottom to top in a slow motion)
If so, you do not need to make such a notification control in your app UI by yourself. The UWP communitytoolkit has an existing InAppNotification control. You could use it in your app directly.
Related
In my Universal Windows 10 app, I have an animation that shrinks a custom control whose looks is applied via a template. It works as expected the first time it is run. The second time it is run, the start of the animation is rendered in a horrible resolution, apparently tainted by the previous run:
First time is on the left; second time on the right.
If, instead of using a custom control with a template, I hardcode everything in XAML, the problem doesn't occur.
If I grow rather than shrink the target, the problem doesn't occur.
Let me start with the non-templated version, which is shorter and easier to read than the templated version:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122"
Text="Q">
<TextBlock.RenderTransform>
<ScaleTransform x:Name="transform" />
</TextBlock.RenderTransform>
</TextBlock>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked" />
</Grid>
</Page>
The code-behind is as follows:
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
}
private void OnAnimateClicked(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(this, "Hide", useTransitions: false);
VisualStateManager.GoToState(this, "Show", useTransitions: true);
}
}
This works fine every time. But. Instead of applying the ScaleTransform to the TextBlock's RenderTransform directly, I have a custom control with a template applied. For illustration purposes we can use a custom control that is little more than a placeholder:
public sealed class CustomControl : Control
{
}
Then change the XAML to replace the TextBlock with a CustomControl, applying a template to the CustomControl:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp">
<Grid>
<Grid.Resources>
<Style TargetType="local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomControl">
<Grid>
<TextBlock Text="Q" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:CustomControl
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122">
<local:CustomControl.RenderTransform>
<ScaleTransform x:Name="transform" />
</local:CustomControl.RenderTransform>
</local:CustomControl>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked"/>
</Grid>
</Page>
The first time I click the Animate button, this works exactly like the first version. The second and subsequent times, the initial animation rendering uses the really coarse resolution shown on the right:
The coarseness seems to be proportional to the shrinkage factor. Is this a bug of some sort (a failed optimization?), or is my understanding of templates flawed?
I'am very new to this WinRT and XAML stuff and not sure how to achieve this goal. For my page layout I have basically 2 rows. The first row is representing my (static) basic menu with some buttons and pictures (about 130 height). The rest of the screen should be used to display content. Like this:
screen layout
now when a user clicks on a main menu button the submenu "filter settings" should be move down with an animation. The main content is also responding to this event and moving accordingly ("filter settings" should not overlay the main content).
My current idea to define this layout is using a grid with 3 rows and 2 frames placed inside it. When no filter is activated, I use rowspan for my main content to span over the whole area. When a click event is recognized, I change the rownum of the frame which hold the main content (ModuleContentFrame) to 2 and its rowspan to 1. Then I'am loading the filter page to frame ModuleFadeInFrame.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="130"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Frame
x:Name="ModuleFadeInFrame"
Grid.Row="1"/>
<Frame
x:Name="ModuleContentFrame"
Grid.Row="1"
Grid.RowSpan="2"/>
</Grid>
My question is: is this layout definition with a grid and frames inside it a suitable solution to solve this problem and how can I achieve a "moving" animation when displaying a sub-menu. I tried this with an Storyboard but there the main content is just "jumping" to row 2
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ModuleContentFrame"
Storyboard.TargetProperty="(Grid.Row)">
<DiscreteObjectKeyFrame KeyTime="1" Value="2" />
</ObjectAnimationUsingKeyFrames>
You can't really animate Grid row/col/etc... changes. Also any animation that'll result in a layout change is a dependent animation - and has bad performance. What I'd do is something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="App1.MainPage"
mc:Ignorable="d">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MenuState">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="ClosedState"/>
<VisualState x:Name="OpenState">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid Margin="0,50,0,0" Background="Black">
<TextBlock>
Long text blablabla
</TextBlock>
</Grid>
<Grid x:Name="grid" Margin="0,50,0,0" Height="50" VerticalAlignment="Top" Background="#77ffff00">
<Grid.RenderTransform>
<CompositeTransform TranslateY="-50"/>
</Grid.RenderTransform>
<Button Content="Close" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="ClosedState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
<Grid Margin="0,0,0,0" Height="50" VerticalAlignment="Top" Background="Red">
<Button Content="Open" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="OpenState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
</Grid>
</Grid>
</Page>
This way there's no layout change, as your submenu is going to end up on top of the content.
if you're really insisting on the 'not obscuring content' way
You could just have your submenu before your content with a Height="0", and animate the height of the element with a DoubleAnimation. If you do this, you'll have to set EnableDependentAnimation to true.
More info: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx
Thank you Tamás, you helped me a lot getting my solution. I'am doing this now as follows:
This code goes into the edit:UserControl for each submenu. On the main page I then only have to handle my Button click events and call the appropriate Animation. Next Step is getting familiar with Blend as you suggested :-)
I marked your post as answer because it was the most helpful in finding my solution
<Grid x:Name="maingrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RenderTransform>
<CompositeTransform TranslateY="-360"/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="myStoryboardOpen">
<DoubleAnimation Duration="0:0:0.3" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="myStoryboardClose">
<DoubleAnimation Duration="0:0:0.3" To="-360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
</Grid.Resources>
i am having quite trouble with my Images and Canvases when the user tries to snap in a View/App on the Left site. I already declared a method and a delegate on
Window.Current.SizeChanged += OnWindowSizeChanged;
But this isn't really cool because I already have a pinchZoom. I really don't want the view to get downsized when the AppWindow gets resized. Is there any Parameter I can set that the view is not resized on that event?
<Grid Height="758" Grid.RowSpan="2" Width="10000" ManipulationMode="All" x:Name="paper" PointerWheelChanged="scrolled" ManipulationDelta="PaperManipulation" >
<Grid.RenderTransform>
<CompositeTransform></CompositeTransform>
</Grid.RenderTransform>
<Image Source="images/page.png" x:Name="backgroundpaper" HorizontalAlignment="Left" Height="758" Width="10000" Margin="10,0,0,0" VerticalAlignment="Top" />
<Grid Margin="240,140,0,0" Height="600" x:Name="canvases" ManipulationMode="All" VerticalAlignment="Center">
<Grid.RenderTransform>
<CompositeTransform></CompositeTransform>
</Grid.RenderTransform>
<Canvas Tapped="canvasTapped" Background="Transparent" ManipulationMode="All" RenderTransformOrigin="0.5, 0.5" x:Name="background_canvas" Height="600" VerticalAlignment="Top" Width="600" HorizontalAlignment="Left">
</Canvas>
.... // SOME MORE ELEMENTS
</Grid>
</Grid>
Thanks so far.
Can you check with your code in XAML ?
I think you set some Width there.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="Snapped">
<Storyboard>
//check your code here in snapped view handling
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
I've got an application with two XAML/WPF windows (derived from NavigationWindow), each window contains one parent UserControl, in which all child controls are placed. In one of the windows, I'd like to show the second window's content (really just the parent UserControl), in the manner like a picture-in-picture TV. In this way the user could view the first window, and see what is happening in the second window at the same time. Note, that I do not want two independent copies of this second window's UserControl (that would be easy), but to mirror the content of the second window in the first window.
This is vaguely similar to the Windows 7 Taskbar thumbnail previews, so I figure that it must be doable. Ideally, however, I'd also like to be able to interact with that window-in-a-window, in the same way as I would if I were to pull up the original window.
This is similar to this question, except that I'd like just a single window from the same application to be copied, instead of the whole desktop. Also similar to this question, but I need a bit more hand-holding, as I'm not super-familiar with C#/WPF. Some code snippets would be great.
Thank you in advance!
Use a visual brush. It will not be interactive, but that seems to suit your needs.
Paste this code into Kaxaml to see it in action.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Triggers>
<EventTrigger RoutedEvent="Page.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard Storyboard.TargetName="sampleAnimation" Storyboard.TargetProperty="(FrameworkElement.RenderTransform).(RotateTransform.Angle)">
<DoubleAnimation Duration="00:00:10" RepeatBehavior="Forever" To="-360">
<DoubleAnimation.EasingFunction>
<ElasticEase/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Page.Triggers>
<Page.Resources>
<VisualBrush x:Key="contentBrush" Stretch="None" Visual="{Binding ElementName=content}"/>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock FontSize="25" Text="Content to mirror:"/>
<Grid
x:Name="content"
Grid.Row="1"
Margin="5"
Background="#11000000"
ClipToBounds="True">
<TextBox
x:Name="sampleAnimation"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="60"
FontWeight="Light"
Foreground="Red"
RenderTransformOrigin="0.5,0.5"
Text="Hello!">
<TextBox.RenderTransform>
<RotateTransform Angle="0"/>
</TextBox.RenderTransform>
</TextBox>
</Grid>
<TextBlock Grid.Row="2" FontSize="25" Text="Mirrored content using VisualBrush:"/>
<Grid Grid.Row="3" Background="{StaticResource contentBrush}">
</Grid>
</Grid>
</Page>
Use a visual brush as a fill on a rectangle.
You won't be able to interact with it though... but this is how preview thumbnails on the taskbar are accomplished.
<Grid HorizontalAlignment="Left" Name="A" Height="100" Width="100">
<Grid.Background>
<SolidColorBrush Opacity="0" Color="White"/>
</Grid.Background>
<!-- Contents -->
</Grid>
<Rectangle Name="RA" VerticalAlignment="Top" Width="100" Height="100" HorizontalAlignment="Left" Stroke="Black">
<Rectangle.Fill>
<!-- Creates the reflection. -->
<VisualBrush AutoLayoutContent="True" Visual="{Binding ElementName=A}" ViewboxUnits="RelativeToBoundingBox" ViewportUnits="RelativeToBoundingBox" Stretch="Fill" AlignmentX="Left" AlignmentY="Top" Viewport="0,0,1,1" Viewbox="0,0,1,1" TileMode="None">
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
To interact, you'd have to bind all the properties to an identical screen, and use a layout transform to shrink it.
<StackPanel>
<Grid>
<TextBox Name="A"/>
</Grid>
<Grid>
<Grid.LayoutTransform>
<ScaleTransform CenterX=".5" CenterY=".5" ScaleX=".25" ScaleY=".25"/>
</Grid.LayoutTransform>
<TextBox Name="B" Text="{Binding ElementName=A, Path=Text, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</StackPanel>
I’m trying to create a simple image rotator control where a user can click an arrow and an image will slide to another one. I’m doing this with a stackpanel of images inside of a scrollviewer.
n silverlight, the following code works as expected:
<Grid x:Name="RootLayout" Margin="200" Width="480">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Row="0" Grid.Column="0" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<StackPanel Orientation="Horizontal">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="tt" />
</StackPanel.RenderTransform>
<StackPanel.Resources>
<Storyboard x:Name="sb">
<DoubleAnimation
Storyboard.TargetName="tt"
Storyboard.TargetProperty="X"
From="0"
To="-50"
Duration="0:0:0.25" />
</Storyboard>
</StackPanel.Resources>
<Rectangle Width="50" Height="50" Fill="Blue" />
<Rectangle Width="50" Height="50" Fill="Green" />
</StackPanel>
</ScrollViewer>
<Button Content="Push" Click="test" Grid.Row="1" Grid.Column="1" />
</Grid>
The "Push" button simply begins the storyboard.
Now, when I use this same code in a wp7 page, I get a runtime error on the Begin method of the storyboard saying that the targetname could not be resolved. Interestingly enough, if I remove the ScrollViewer wrapped around the StackPanel completely, the page runs just fine. Why would it fail on wp7 when the stackpanel is contained inside the scrollviewer? (Note that the root level of the phone page is phone:PhoneApplicationPage)
Thanks!
Can't answer why there is a difference, but generally when I have been writing storyboards on WP7 I reference the transform I want like this.
Storyboard.TargetName="myStackPanel" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)
Perhaps there is a difference in the traveral algorithms.