WPF Choppy / Jittery Animation related to window size - wpf

I'm trying to create a slide out menu for my WPF Application, however I've noticed that the animation gets jittery / laggy depending on the size of the screen. I've tried googling but haven't really found any solutions and nobody else even mentions screen size.
Heres my XAML Code:
<Grid x:Name="sideMenu" Visibility="Collapsed" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="2" Background="White" >
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RenderTransform>
<TranslateTransform X="350" Y="0"/>
</Grid.RenderTransform>
<Border Grid.ColumnSpan="2" Grid.RowSpan="4" BorderBrush="Black" BorderThickness="1 0 0 0"></Border>
<Border Background="#253031" BorderBrush="Black" Grid.ColumnSpan="2" BorderThickness="0 0 0 1"></Border>
<Label Content="Menu Heading" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Top" Foreground="White" FontSize="18" Margin="5" />
</Grid>
Also here are my following storyboard animations
SlideIn:
<Storyboard x:Key="SlideIn" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)">
<DoubleAnimation To="0" From="350" Duration="0:0:0.2"/
</Storyboard>
SlideOut:
<Storyboard x:Key="SlideOut" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)">
<DoubleAnimation To="350" From="0" Duration="0:0:0.2"/
</Storyboard>
And finally here's the code behind that activates the storboard animations:
private void ShowMenu()
{
//Start the slide animation
Storyboard animation = Resources["SlideIn"] as Storyboard;
animation.Begin(sideMenu);
}
private void HideMenu()
{
Storyboard animation = Resources["SlideOut"] as Storyboard;
animation.Begin(sideMenu);
}
any thoughts or suggestions would be much appreciated!

Related

Viewbox and Canvas

this is my first intervention here. I'm sorry in advance for my poor english and i wish i will be clear.
I'm Making a custom control. (i'm a beginner in wpf) his goal is depending of a Property "Type Control". It could be a simpe textblock displaying data (and change background color depending on level property), it could be a marquee text or could be a picture.The goal here is to make a dynamic control. I explain this but my real trouble his the marquee part.
This is my XAML code :
<ControlTemplate TargetType="{x:Type local:ControlPerso}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" x:Name="PART_BORDER" VerticalAlignment="Stretch" CornerRadius="10" Height="Auto">
<Viewbox Margin="2" StretchDirection="DownOnly" x:Name="PART_VB" Stretch="Fill">
<Grid x:Name="PART_GRID" ShowGridLines="false" VerticalAlignment="Center" Height="Auto" >
<Grid.RowDefinitions>
<RowDefinition x:Name="PART_ROWLABEL"></RowDefinition>
<RowDefinition x:Name="PART_ROWSCROLL"></RowDefinition>
<RowDefinition x:Name="PART_ROWIMAGE"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="RowLabel" VerticalAlignment="Center">
<TextBlock x:Name="PART_LABEL" Text="{Binding MyText, RelativeSource='{RelativeSource Mode=TemplatedParent}', UpdateSourceTrigger=PropertyChanged}" Background="Transparent"
FontFamily="Verdana" FontSize="{Binding FontSize, RelativeSource='{RelativeSource Mode=TemplatedParent}'}" FontWeight="ExtraBold" HorizontalAlignment="Center">
<TextBlock.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="2" Opacity=".9" Softness="0.3" />
</TextBlock.BitmapEffect>
</TextBlock>
</Grid>
<Grid Grid.Row="1" x:Name="RowScroll" VerticalAlignment="Center">
<Canvas x:Name="PART_ContentControl" ClipToBounds="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="{Binding ActualHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=TemplatedParent}}" >
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard x:Name="ContentTickerStoryboard" Storyboard.TargetProperty="(Canvas.Left)">
<DoubleAnimation Storyboard.TargetName="PART_Content" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<ContentPresenter x:Name="PART_Content"
HorizontalAlignment="{TemplateBinding ContentControl.HorizontalAlignment}"
VerticalAlignment="{TemplateBinding ContentControl.VerticalAlignment}"
Content="{Binding MyText, RelativeSource={RelativeSource Mode=TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" TextBlock.FontSize="{Binding FontSize, RelativeSource='{RelativeSource Mode=TemplatedParent}'}">
<ContentPresenter.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="2" Opacity=".9" Softness="0.3" />
</ContentPresenter.BitmapEffect>
</ContentPresenter>
</Canvas>
</Grid>
<Grid Grid.Row="2" x:Name="RowImg" ShowGridLines="False" VerticalAlignment="Center" Height="Auto">
<Image Source="C:\Users\Zebody\Pictures\thk.jpg"/>
</Grid>
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
My trouble : Viewbox works fine with the grid row's picture and grid's row "label" (resize the font perfectly). But it's not working with rowscroll (marquee part). The font never resize. It seems it's because the canvas. If i remove height and width, resizing works but canvas doesnot fill my custom control.
What i Whant to do : The canvas fill all my custom control and could resize the font when i resize my custom control (in a mainwindow).
Could anyone help me how to do ?
Thx in advance and sorry again for my poor english

WPF Animation dependency issue

I just started to learn WPF and XAML and I tried to gete an animation sample to work on my machine. Basically, a label background should change when a specific value is set in the corresponding textbox.
Issue is I get the following error: Background' property does not point to a DependencyObject in path '(0).(1)
This is the XAML:
<Window x:Class="WpfDataBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfDataBinding"
Title="MainWindow" Height="350" Width="264.828">
<Window.Resources>
<DataTemplate DataType="{x:Type loc:Person}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="210"/>
</Grid.ColumnDefinitions>
<TextBlock Name="nameLabel" Grid.Row="0" Grid.Column="0" Text="Name:" FontSize="14" Margin="3,3,0,0"/>
<TextBox Name="nameTextBox" Grid.Row="0" Grid.Column="1" Width="200" Text="{Binding Name}" FontSize="14" Margin="3" />
<TextBlock Name="ageLabel" Grid.Row="1" Grid.Column="0" Text="Age:" FontSize="14" Margin="3,3,0,0"/>
<TextBox Name="ageTextBox" Grid.Row="1" Grid.Column="1" Width="200" Text="{Binding Age}" FontSize="14" Margin="3"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Age}" Value="21">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="ageLabel"
Storyboard.TargetProperty="(Label.Background).(SolidColorBrush.Color)"
To="Red" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<Grid Margin="0,0,0,-0.2" HorizontalAlignment="Left" Width="248">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding}" />
<StackPanel Grid.Row="2" Grid.ColumnSpan="2">
<Button Content="_Show.." Click="Button_Click"/>
<Button Content="_Age" Click="Button_Click_1"/>
</StackPanel>
</Grid>
Thank you
In order to animate the Color property of a SolidColorBrush in the Background property of a UI Element, you need to first set the Background. The default value of the Background property of a TextBlock is null, so there is nothing to animate.
So, first set a Background before animating it:
<TextBlock ...>
<TextBlock.Background>
</SolidColorBrush Color="Transparent"/>
</TextBlock.Background>
</TextBlock>
Now your could write the TargetProperty path like
Storyboard.TargetProperty="Background.Color"
or
Storyboard.TargetProperty="(TextBlock.Background).Color"
or
Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)"
or even
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
All expressions are equivalent. The details are explained in the PropertyPath XAML Syntax article on MSDN.
As per this question you need to use:
ColorAnimation Storyboard.TargetName="ageLabel"
Storyboard.TargetProperty="(TextBlock.Background).Color"
To="Red" Duration="0:0:1"/>
rather than (TextBlock.Background).(SolidColorBrush.Color) as apparently Background and SolidColorBrush are the same object.
(Label.Background).(SolidColorBrush.Color) line is the problem. It needs to be <ColorAnimation Duration="0" To="Red" Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)" Storyboard.TargetName="ageLabel" />

WPF Adorner Newbee

Using VB.Net & WPF
I'm Using Code Available at Overlaying Controls in WPF with Adorners (Converted to VB.Net)
MainWindow.xaml
<Window x:Class="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">
<Grid Name="G1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text=" This is Parent Control " HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Grid.Row="1" Content="Show Child Control " HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"/>
</Grid>
</Window>
Code Behind
Class MainWindow
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim U1 As New UserControl1
Using OverlayAdorner(Of UserControl).Overlay(G1, U1)
End Using
End Sub
End Class
UserControl1.xaml
UserControl x:Class="UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background=" #44000000">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text=" This is Child Control " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
<TextBox Name="T1" Grid.Row="1" Margin="5"/>
<Button Grid.Row="2" Content="Close Child Control " HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" Margin="5"/>
</Grid>
</Grid>
</UserControl>
Code Behind
Public Class UserControl1
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
End Sub
Public Property UserInput As String
Get
Return T1.Text
End Get
Set(value As String)
T1.Text = value
End Set
End Property
End Class
Now when user clicks on button in mainwindow, usercontrol1 should open as adorner and allow user to enter some text in textbox and when user clicks button in usercontrol1 it should close and return text to mainwindow where it would be displayed as message box.
Please Help me to achive the same as i'm newbie in wpf
I attempted to write a pure xaml based solution, you may adjust as per your needs
in this sample there are 2 textboxes 1st is regular while other popups a list when focused and allow you to select an item from it
sample code
<Grid>
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Grid.Resources>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
MinWidth="200">
<TextBox Text="regular textbox" />
<TextBox Text="{Binding SelectedItem,ElementName=list,TargetNullValue=select an item}">
<TextBox.Triggers>
<EventTrigger RoutedEvent="GotFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="button"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame Value="true"
KeyTime="0:0:0" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBox.Triggers>
</TextBox>
</StackPanel>
<Border Background="#77000000"
Visibility="{Binding IsChecked,ElementName=button,Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="300"
Height="150">
<ListBox x:Name="list">
<sys:String>item 1</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 3</sys:String>
<sys:String>item 4</sys:String>
<ListBox.Triggers>
<EventTrigger RoutedEvent="MouseLeftButtonUp">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="button"
Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame Value="False"
KeyTime="0:0:0" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ListBox.Triggers>
</ListBox>
<ToggleButton IsChecked="False"
x:Name="button"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Content="X"
ToolTip="Close" />
<Grid.Effect>
<DropShadowEffect Opacity=".5" />
</Grid.Effect>
</Grid>
</Border>
</Grid>
content of the grid inside the border is where you'll place your user control
just copy this code to a new project's main window and run it. give it a try and see if this is close to your needs, we can work out to fit it according to your needs.

WPF keyboard navigation: How to expand a panel and put focus in the first control of that panel?

Kind of new to WPF and I am working on an app that has a general user input form and a "details" section that is hidden in an Expander. I am trying to get it so that if the user Tabs into the expander control it will automatically expand and put focus into the first control within that expander.
Some stripped down XAML:
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Label Content="Email" Grid.Row="0" Grid.Column="0"/>
<TextBox Grid.Row="0" Grid.Column="1"/>
<Label Content="Department" Grid.Row="0" Grid.Column="2"/>
<TextBox Grid.Row="0" Grid.Column="3"/>
<Label Content="Contact Name" Grid.Row="1" Grid.Column="0"/>
<TextBox Grid.Row="1' Grid.Column="1"/>
<Label Content="Phone Number" Grid.Row="1" Grid.Column="2"/>
<TextBox Grid.Row="1" Grid.Column="3"/>
</Grid>
<Expander ExpandDirection="Down" IsExpanded="False" Header="Details">
<StackPanel Orientation="Horizontal">
<Label Content="Address"/>
<TextBox />
<Button Content="Add Another" />
</StackPanel>
</Expander>
</StackPanel>
What I would like to do is that if the user is currently entering in the Phone number and hits tab the Details Expander should expand and put focus into the Address's text box. I've tried setting TabIndex and playing with KeyboardNavigation.Tab... without any luck.
Any ideas how to do this?
Replace your Expander with following XAML using an EventTrigger and a Storyboard:
<Expander ExpandDirection="Down"
IsExpanded="False"
Header="Details">
<Expander.Style>
<Style>
<Style.Triggers>
<EventTrigger RoutedEvent="Expander.GotFocus">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetProperty="(Expander.IsExpanded)">
<DiscreteBooleanKeyFrame
KeyTime="00:00:01"
Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<StackPanel Orientation="Horizontal">
<Label Content="Address"/>
<TextBox />
<Button Content="Add Another" />
</StackPanel>
</Expander>
I don't think there is a pure Xaml approach for this. You may have to handle the expander's GotFocus event to 1) expand the expander, and 2) the call the Focus() method on the first control.

WPF Grid Show/Hide Column

I have the following layout in my grid
<Grid>
<Grid.RowDefinitions >
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Button Click="Button_Click" Grid.Row="0" Width="50" Grid.Column="2" Content="Test" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="1" Background="red" />
<StackPanel Grid.Column="1" Grid.Row="1" Background="Blue" />
<GridSplitter x:Name="gs" Grid.Column="1" Grid.Row="1" Width="10" />
<StackPanel x:Name="green" MinWidth="100" Grid.Column="2" Grid.Row="1" Background="Green" />
</Grid>
</Grid>
I essentially want this layout when the button is pressed:
<StackPanel Grid.Column="0" Grid.Row="1" Background="red" />
<StackPanel Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Background="Blue" />
<!--<GridSplitter x:Name="gs" Grid.Column="1" Grid.Row="1" Width="10" />
<StackPanel x:Name="green" MinWidth="100" Grid.Column="2" Grid.Row="1" Background="Green" />-->
And this layout when the button is pressed again:
<StackPanel Grid.Column="0" Grid.Row="1" Background="red" />
<StackPanel Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1" Background="Blue" />
<GridSplitter x:Name="gs" Grid.Column="1" Grid.Row="1" Width="10" />
<StackPanel x:Name="green" MinWidth="100" Grid.Column="2" Grid.Row="1" Background="Green" />
How Can I make the gridsplitter and last panel disappear, and have the panel in the middle column fill it's place? (and vice-versa) Is there a way to change the column span at runtime?
Thanks!
You can use triggers or you can use a storyboard/animation the fires when you button is clicked.
you want to do something like this.....
<Window.Resources>
<Storyboard x:Key="OnClick1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="gs" Storyboard.TargetProperty="(FrameworkElement.Width)">
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="green" Storyboard.TargetProperty="(FrameworkElement.MinWidth)">
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Window.Triggers>
in order to reverse this animation, you should use something to maintain state, say use a ToggleButton and use the ToggleButton.Checked && ToggleButton.Unchecked routed events. Or, add a dependency property to your codebehind that maintains the state.
I think the main problem is remembering to change the MinWidth attribute as well. MinWidth will override actual width.

Resources