RenderTransform.TranslateTransform animating in usercontrol in wpf - wpf

i want to create a wpf usercontrol that displays an Image and has a toolbar panel,
i want to set features listed below to the my userControl:
tool bar panel hidden when mouse cursor is out side of the usercontrol.
When mouse cursor enter the usercontrol,toolbar panel move up from the bottom of the usercontrol and locate at the bottom of the usercontrol.
i create it but ,i have a problem ,
see bellow:
when mouse cursor enter the UserControl:
and when mouse cursor leaved UserControl:
My Problem:
when panel is moving out side of the UserControl,the out side parts must be invisible,
like bellow:
my UserControl's Xaml codes:
<UserControl.Resources>
<Storyboard x:Key="SB_MouseEnter">
<DoubleAnimation To="0" Storyboard.TargetName="button_panel" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" Duration="0:0:0.2"/>
</Storyboard>
<Storyboard x:Key="SB_MouseLeave">
<DoubleAnimation To="40" Storyboard.TargetName="button_panel" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" Duration="0:0:0.2"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource ResourceKey=SB_MouseEnter}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource ResourceKey=SB_MouseLeave}"/>
</EventTrigger>
</UserControl.Triggers>
<Border CornerRadius="4" BorderBrush="SeaGreen" BorderThickness="2">
<Grid>
<Image Source="Images/Koala.jpg"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Name="button_panel" Height="40" RenderTransformOrigin="0.5,0.5">
<StackPanel.RenderTransform>
<TranslateTransform Y="40"/>
</StackPanel.RenderTransform>
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="1"/>
<GradientStop Color="#66FFFFFF"/>
</LinearGradientBrush>
</StackPanel.Background>
<Button Padding="5" Margin="5,0" Width="80" Height="30">
Open
</Button>
<Button Padding="5" Margin="5,0" Width="80" Height="30">
Clear
</Button>
</StackPanel>
</Grid>
</Border>

Just Clip the button_panel when it leaves the Border with ClipToBounds="True" on the Border
something like:
...
<Border BorderBrush="SeaGreen"
BorderThickness="2"
ClipToBounds="True"
CornerRadius="4">
...
Now with ClipToBounds="True" being set on the Border, any child of the Border which is outside the Border is not going to be visible.
This would thus satisfy your requirement of having the StackPanel invisible when the mouse is not over the image as well since TranslateTransform keeps it outside the Border. Thus you only see the StackPanel when mouse is over the image and the Slide in/out is only visible inside the Border.

Related

Adding content/text in rectangle WPF

This is my code for rectangle :
<Rectangle x:Name="rect1" Grid.Column="1" Fill="#FF5C626C" HorizontalAlignment="Left" Height="50" Margin="36,171,0,0" StrokeThickness="2" VerticalAlignment="Top" Width="358" RadiusX="30" RadiusY="50">
<Rectangle.Triggers>
</Rectangle.Triggers>
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="#FF767C84" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Rectangle.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="#FF5C626C" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
My question is how do i add a text/content in the rectangle ?
One might suggest using a code block, but if u go through my code, youu'll notice that the rectangle changes it's color on mouseover.So if i put a textblock over the rectangle,the mouseover doesn't work properly(as the textblock covers the entire rectangle).
Another suggestion would be to use a border.But i am not sure about this as i need to find the code to apply mouse over effect on a border.
The next suggestion might be to use a button instead.I would've but my rectangle has corner radius and is a bit round-shaped which, if i use a button, would be hard to achieve.
So how do i add content/text inside the rectangle?
If you feel you definitely have to use a rectangle, put it in a grid and add a TextBlock element above it.
By setting the TextBlock's IsHitTestVisible property to False all hit-testing (mouse events) will be ignored on it and fall through to your rectangle.
<Grid>
<Rectangle (...your attributes here...)>
(...your rectangle code here...)
</Rectangle>
<TextBlock Text="Hello World!" IsHitTestVisible="False" />
</Grid>

Animating Image in MVVM

I have a view of a viewmodel as defined below
<DataTemplate DataType="{x:Type local:TestViewModel}">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Button Name="btnStart" Command="{Binding Start}" Margin="5,0,5,0" />
<Button Name="btnCancel" Command="{Binding Cancel}" Margin="5,0,5,0" />
</StackPanel>
</Grid>
</DataTemplate>
So when i click on startButton , I want to start an animation i.e i want to move an arrow image from top of my screent to bottom.
I tried defining the image in grid, defining storyboard in style and attaching datatrigger to property .But this is causing the whole ui to expand rather than the animation moving over the screen.
I want the animation to move over my stackPanel. How do i do that?
Please try the next animation example(it used the TranslateTransform of the Image):
<Grid x:Name="AnimationAreaRootGrid">
<Image x:Name="Image" HorizontalAlignment="Left" VerticalAlignment="Top" Source="Res/Koala.jpg" Width="50" Height="50" RenderTransformOrigin="1.0,1.0">
<Image.RenderTransform>
<TranslateTransform />
</Image.RenderTransform>
</Image>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" >
<Button Name="btnStart" Content="Animate Down" Margin="5,0,5,0">
<Button.Resources>
<Storyboard x:Key="DownMovingStoryBoardKey" Storyboard.TargetName="Image">
<!--From - the animation start point-->
<!--From - the animation end point-->
<DoubleAnimation Storyboard.TargetProperty="(Control.RenderTransform).(TranslateTransform.Y)"
From="0"
To="250"
Duration="0:0:1" />
</Storyboard>
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource DownMovingStoryBoardKey}"/>
</EventTrigger>
</Button.Triggers>
</Button>
<Button Name="btnCancel" Margin="5,0,5,0" Content="Animate Up">
<Button.Resources>
<Storyboard x:Key="UpMovingStoryBoardKey" Storyboard.TargetName="Image">
<!--From - the animation start point-->
<!--From - the animation end point-->
<DoubleAnimation Storyboard.TargetProperty="(Control.RenderTransform).(TranslateTransform.Y)"
From="250"
To="0"
Duration="0:0:1" />
</Storyboard>
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource UpMovingStoryBoardKey}"/>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Grid>
Explanations
A clicking on a btnStart will trigger the Down moving animation so the image will be moved down.
A clicking on a btnCancel will trigger the Up moving animation so the image will be moved up.
Regards.
I would use a Canvas and have your Image animated by changing Canvas.Left/Canvas.Top -values.
Canvas, unlike StackPanel, is not affected by it's children when it is doing it's own layout. The downside is that you would have to locate your StackPanel's coordinates, if the animation by the StackPanel coordinates is a requirement.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Canvas>
<Image ... />
</Canvas>
<Button Name="btnStart" Command="{Binding Start}" Margin="5,0,5,0" ></Button>
<Button Name="btnCancel" Command="{Binding Cancel}" Margin="5,0,5,0"></Button>
</StackPanel>
How about using a TranslateTransform to animate your Image? Use it with the UIElement.RenderTransform property and you won't affect the layout of the rest of your view.
More infos on WPF transforms:
https://msdn.microsoft.com/en-us/library/ms750596(v=vs.100).aspx
General overview for WPF animations:
https://msdn.microsoft.com/en-us/library/ms752312(v=vs.100).aspx

Access ItemsControl Items and Animate One by One

Today is a good day since I started with WPF, this for a launcher I'm creating.
Using the following code, I managed to get the result to be seen in the screenshot:
<Grid>
<ItemsControl ItemsSource="{Binding Programs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}" Background="Transparent" Foreground="White" Width="128" Height="150" >
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform />
</TransformGroup>
</Button.RenderTransform>
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Image}" Height="128" />
<ContentPresenter Grid.Row="1" HorizontalAlignment="Center" Margin="3,10" />
<Rectangle Grid.Row="0" Fill="{TemplateBinding Background}" />
<Rectangle Grid.Row="1" Fill="{TemplateBinding Background}" />
</Grid>
</ControlTemplate>
</Button.Template>
<Button.Resources>
<Storyboard SpeedRatio="4" x:Key="MouseEnterStoryboard" x:Name="MouseEnterStoryboard">
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="#22FFFFFF"></ColorAnimation>
</Storyboard>
<Storyboard SpeedRatio="4" x:Key="MouseLeaveStoryboard" x:Name="MouseLeaveStoryboard">
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="Transparent"></ColorAnimation>
</Storyboard>
<Storyboard Duration="00:00:00.05" x:Key="MouseClickStoryboard" AutoReverse="True">
<DoubleAnimation To="0.8" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"/>
<DoubleAnimation To="0.8" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"/>
</Storyboard>
<Storyboard x:Key="WindowLoadedStoryboard">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="00:00:01" />
</Storyboard>
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource MouseEnterStoryboard}" />
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource MouseLeaveStoryboard}" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource MouseClickStoryboard}" />
</EventTrigger>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard Storyboard="{StaticResource WindowLoadedStoryboard}"></BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Screenshot:
Now, for each item in the list bound to this control, it will create a button.
How would I access this button programmatically, better yet, how would I access one of the Storyboards programatically since assigning a name (x:to them simply won't do the trick it seems...
Also, how can I animate the buttons one by one? Currently they each fade in at exact the same time (# WindowLoadedStoryboard), but I would like to let each button fade in one by one with a short delay, to create a nice effect. How would I achieve this?
Hope someone can answer these 2 questions for me!
Greetings!
Your problem with accessing the elements defined in the DataTemplate is caused because you defined those elements in a DataTemplate... those elements could be rendered in many different types of UI container controls. You can find the solution in the How to: Find DataTemplate-Generated Elements page from MSDN.
You first need to get hold of the relevant container control that contains the item that has had that DataTemplate applied to it. Next, you need to get the ContentPresenter from that container control and then you can get the DataTemplate from ContentPresenter. Finally, you can access the named elements from the DataTemplate. From the linked page:
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.
ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
TextBlock myTextBlock =
(TextBlock)myDataTemplate.FindName("textBlock", myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: " +
myTextBlock.Text);

Button animation on view model property change?

I have the following xaml code. The XAML displays an animation on the button whenever the button is click. I want to start/stop the animation whenever a boolean property in the view model is changed. Any help is appreciated in advance.
<Button Name="button5" Width="100" Margin="10" HorizontalContentAlignment="Left">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Width" From="0" To="94" Duration="0:0:1" AutoReverse="True" RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<Button.Content>
<Grid Width="94">
<Border HorizontalAlignment="Left" Width="0" Name="myBorder">
<Border.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.115" Color="Black" />
<GradientStop Offset="0.715" Color="Red" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<TextBlock FontSize="14" HorizontalAlignment="Center">Search</TextBlock>
</Grid>
</Button.Content>
</Button>
Also how can i animate the button in such a way that once the border width has reached its max width a reverse animation should occur. I mean i want a wave like effect(using gradient) inside the button. The wave should turn back once it hits the rightmost end of the button. Same should repeat indefinitely. This animation will be controlled using a ViewModel boolean property.

WPF: How to fade-in and scale a user control in a popup

I have a user control that I'd like to show when the user clicks a button.
That's not a problem, using af Popup control.
However, I'd like to have the user control fade-in and scale from 0.5 to 1.2 and back to 1.0 (both X and Y) at the same time.
How do I do that?
WPF Popups are not transparent, so fade in and fade out won't really work. You can set Opacity all you want, but that won't change a thing. However, you could play with the Tooltip. It's pretty close to a popup. Anyway, here's something to get you started:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Style>
<Style>
<Style.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="00:00:02" From="0" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="FrameworkElement.Visibility" Value="Collapsed">
<Setter Property="FrameworkElement.Opacity" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Style>
<Border x:Name="border" BorderBrush="Blue" BorderThickness="3" CornerRadius="3" Padding="3" Background="Orange"
Width="175" Height="175">
<TextBlock Text="Sample" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
plop it somewhere, I am using a tooltip on the same button, just for demonstration purpose:
<Button Click="OnButtonClick" Content="click to see popup">
<Button.ToolTip>
<ToolTip x:Name="popup" IsOpen="False" Background="Transparent" BorderBrush="Transparent"
Placement="Bottom">
<WpfApplication1:UserControl1/>
</ToolTip>
</Button.ToolTip>
</Button>
for OnButtonClick code behind, I just toggleed the popup so I can click it more than once:
private void OnButtonClick(object sender, RoutedEventArgs e)
{
popup.IsOpen = !popup.IsOpen;
}
WPF popups can handle transparency, just set the following
<Popup AllowsTransparency="True" PopupAnimation="Fade">

Resources