Changing property of other element on button "click" event (WPF) - c#

I want to create a toggle button which gives rise to a rectangular panel on clicking. Since rectangle is not having click property so I have enclosed it in a button. Please provide me further guidance.
<Window x:Class="AnimatedRectangle.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" BorderBrush="Black" BorderThickness="2" Foreground="White" VerticalAlignment="Stretch" WindowStartupLocation="CenterScreen">
<Grid>
<Button Name="MyButton">
<Button.Template>
<ControlTemplate>
<Rectangle
Name="MyRectangle"
Width="150"
Height="30"
Fill="Cyan"
Margin="0,220,0,0">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
Please visualize it this way : Both the rectangle and button are of same width and initially the button overlaps(or hide in any other way)the rectangle. When the button is clicked then the rectangle appears and it looks like the rectangular body is part of a button.
JUST LIKE we press downward symbol in address bar and the history/suggestions appears in rectangular body. But here I want a button to give rise to a rectangle body rather than a downward symbol like in address bar.
StackOverflow is not letting me post images as I need to have 10 reputation posts :(
Thanks a lot..!!

Related

How to control a storyboard animation from C# and XAML

There's a lot of questions around this on the net, but after reading them, and the MS docs on animation control, I'm unable to mimic storyboard control from XAML event triggers in C# code.
In this XAML file, I have a canvas that I am rotating. I'd like to add interactivity to the rotation,
<Window x:Class="GraphicsBook.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:k="clr-namespace:GraphicsBook;assembly=Testbed2D"
Title="2D Testbed"
KeyDown="KeyDownHandler"
Height="600"
Width="600" >
<DockPanel LastChildFill="True">
<StackPanel x:Name="stack" DockPanel.Dock ="Top" Orientation="Vertical" Background="#ECE9D8">
<Button Name="StartAnimationClick">Start animation</Button>
<Button Name="StopAnimationClick" Click="stopAnimationClick">Stop animation</Button>
<Canvas x:Name="Grid">
<Canvas.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="CanvasRotation" CenterX="300" CenterY="300" Angle="0"/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="StartAnimationClick">
<BeginStoryboard Name="GridRotationStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="CanvasRotation"
Storyboard.TargetProperty="Angle"
From="0.0" To="360.0"
Duration="00:00:10.00" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<!--<EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimationClick">
<StopStoryboard BeginStoryboardName="GridRotationStoryboard"/>
</EventTrigger>-->
</StackPanel.Triggers>
</StackPanel>
</DockPanel>
</Window>
The commented event trigger,
<!--<EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimationClick">
<StopStoryboard BeginStoryboardName="GridRotationStoryboard"/>
</EventTrigger>-->
Does indeed work as expected, that is, if I click the button, the animation stops. However, the version of the XAML above tries to replicate this functionality in C#, but this doesn't work. The click handler looks like this,
private void stopAnimationClick(object sender, RoutedEventArgs e)
{
Debug.Print("Stop animation");
// ???
}
I'm unable to control the animation object in ???, not matter what technique I try to get a handle on it. I must be plumbing the pieces incorrectly somehow, but I can't see what is wrong.
You can mimic what the EventTrigger does by calling BeginAnimation with a second argument of null:
private void stopAnimationClick(object sender, RoutedEventArgs e)
{
CanvasRotation.BeginAnimation(RotateTransform.AngleProperty, null);
}

Which layout elements should I use to implement a submenu with an animation transition

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>

how to move UI element with storyboard?

I've worked with Opacity property in storyboard
but I cant figure it out how to move an UI element like grid stackpanel button ..... in c#?
(I am writing the storyboard in c# not in xaml )
Well, that depends on your actual layout: Do you want to animate a button in a Grid or in a Canvas (could animate the Margin property or the Canvas.Left attached property, respectively)? Do you want to animate the property itself or a transform (the latter would animate a RenderTransform - specifically a TranslateTransform). You would use the RenderTransform if you still want to refer to the "old" position.
One simple way is:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="myButton"
Storyboard.TargetProperty="(Canvas.Left)" From="1" To="350"
Duration="0:0:10" BeginTime="0:0:0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Canvas x:Name="myCanvas" Background="Yellow">
<Button x:Name="myButton" Width="100" Height="30" Canvas.Left="100" Canvas.Top="100" />
</Canvas>
</Grid>
</Window>
it would be better if you use blend for storyboard ..i have genrated a code for stackpanel movement towards right ..just check it..
you can go through this video aslo it's very good it will perfectly work in your case
<Page.Resources>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="hello">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="100"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Name="hello" Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" >
<StackPanel.RenderTransform>
<CompositeTransform/>
</StackPanel.RenderTransform>
<TextBlock Text="hello1" FontSize="50" />
<Button Content="Button" FontSize="50" Click="Button_Click_1" />
</StackPanel>
</Grid>
and to start do this on button click..
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Storyboard1.Begin();
}
for better understand just read about how to use blend..

Binding refreshes all bound controls on animation

When using a color binding like
Background="{Binding Design.LeftBarColor}"
and executing an animation like
<DoubleAnimation From="1" To="0.5" Storyboard.TargetName="appName"
Storyboard.TargetProperty="(Label.Background).(SolidColorBrush.Opacity)"
Duration="0:0:0.25"/>
all of the controls Binding to "Design.LeftBarColor" are refreshed. But I only want to refresh the label's (appName) background color. I just tried to change the binding mode, but this did not work. What am I doing wrong?
Instead of directly using the Design.LeftBarColor Brush for the Background of the Label, you could create a new Background brush for every Label, and bind the new Brush's Color to Design.LeftBarColor.Color.
<Label Name="appName" ...>
<Label.Background>
<SolidColorBrush Color="{Binding Design.LeftBarColor.Color}"/>
</Label.Background>
...
</Label>
Not sure if i am correct about what you are trying to do. I would say if you want to fade out a control on animation, do not target the brush's opacity. Put a border control on top of the label, and modify the border's opacity.
Sample code here:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Red"/>
</Window.Resources>
<Grid>
<Border Name="Container">
<Label Background="{StaticResource MyBrush}">
<Label.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Container"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Label.Triggers>
Lorem ipsum
</Label>
</Border>
</Grid>
</Window>

Reusable auto-scrolling canvas

Okay I made a Scolling canvas (sometimes I put buttons in it that open my programs or do other stuff) it is working perfectly. But I tried making it into a .dll but I noticed that the method I am using is worthless for a .dll as it autoscrolls upon drop and I can't add more to it. so what I want is a empty canvas (or anything really) that auto-scrolls the content and will let me add more items into it. example: buttons, text block, labels etc. and it will scroll all of them.
Edit: I want to be able to drag the control from the toolbox into the window and then add buttons etc onto it and it will auto-scroll them.
Example below. xaml only.. thinking to make it the way I want it has to be coded in c# not xaml. since once it is added as a user control you cannot add other controls, toolbox items to it and expect them to auto-scroll..
<Canvas ClipToBounds="True" x:Name="scrollerCanvas" Height="588">
<Grid x:Name="OurContainer" Height="588" Background="{x:Null}" ClipToBounds="False">
<Grid.Clip>
<RectangleGeometry Rect="0,0,1087,588" RadiusX="30" RadiusY="30" />
</Grid.Clip>
<StackPanel Height="800" Margin="1">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="scroll" />
</StackPanel.RenderTransform>
</StackPanel>
<Grid.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="620" To="-450"
Storyboard.TargetName="scroll" Storyboard.TargetProperty="Y"
Duration="0:0:28" SpeedRatio=".8" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Grid.Triggers>
</Grid>
</Canvas>
you can use a ScrollViewer with a Canvas inside it.

Categories

Resources