Assign an element as the animation target in a controltemplate - c#

I'm trying to set an event trigger to one of my controls inside a ContentTemplate, i'm using a storyboard and a DoubleAnimation nested with a DoubleAnimationUsingKeyFrames when i set the storyboard TargetName to "ContentPopup" wich is a Grid i hold below, but i get an error telling me that:
The name 'ContentPopup' is not in the namespace 'System.Windows.Controls.Grid'.
The animation code on the control template is:
<Grid Margin="0" Width="55" Height="40">
<Grid.Triggers>
<EventTrigger RoutedEvent="m:Pushpin.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="00:00:00.5000000" Storyboard.TargetName="ContentPopup" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" To="1">
...
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
...
</Grid>
The code on the grid i need to animate is:
<Grid Name="ContentPopup"
Background="White"
Opacity="0.85"
RenderTransformOrigin="0,0">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0" ScaleY="0"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
...
</Grid>
MSDN says that the following needs to be done to make an object targetable
and a grid is a FrameworkElement i want the animation to run on every single one of the controls i summon on my main window using this control template, they are a lot of them so i need to use the template.
The question is:
Is there a way to assign the element as a target in the template?

So i found the right way to do it, even though grid is a FrameworkElement you can't access it from the control template, so you need to provide some binding or XAML reference to it in order to work, so with the same exact code just instead of using the Storyboard.TargetName property using the Storyboard.Target with value:
Storyboard.Target="{Binding ElementName=ContentPopup}"
or also:
Storyboard.Target="{x:Reference Name=ContentPopup}"
it worked for me

Related

FlipView EventTrigger for the SelectionChanged event

I'm developing universal app. On one page i decided to use FlipView. I can easily animate SelectionChanged event from code-behind, but i'm just curious if there is a way to animate this event using XAML only. (BTW, UseTouchAnimationsForAllNavigation="True" doesnt work).
So, here's simplified example of what i'm doing :
<FlipView x:Name="MultipleItems">
<FlipView.Triggers>
<EventTrigger RoutedEvent="Selector.SelectionChanged">
<BeginStoryboard>
<Storyboard x:Name="ColorStoryboard">
//do stuff
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<FlipView.Triggers>
</FlipView>
I think this way of usage EventTrigger is fine (as far as SelectionChanged event takes arguments inherited from RoutedEventArgs), but it still gives me runtime error on navigation to page that contains FlipView.
Error is next :
WinRT information: Failed to assign to property 'Windows.UI.Xaml.EventTrigger.RoutedEvent'. [Line: 69 Position: 35]
Additional information: The text associated with this error code could not be found.
I believe there's way to assign that RoutedEvent property correctly, but i didnt find it yet. Also I don't wont to use behaviours for such simple thing.
Can anyone help?
You need to install the Microsoft.Xaml.Behaviors.Uwp.Managed in your project. Then the EventTrigger will be supported in an UWP project.
Then in your XAML use this package like this:
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
Now you can for example change the background color of FlipView like this:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<Storyboard x:Key="std" x:Name="std" >
<ColorAnimation From="Red" To="Transparent" Duration="0:0:3"
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Storyboard.TargetName="flipView"/>
</Storyboard>
</Grid.Resources>
<FlipView x:Name="flipView" ItemsSource="{x:Bind flipviewCollection}">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Media:ControlStoryboardAction Storyboard="{StaticResource std}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<FlipView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageSource}" Stretch="None"/>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Grid>
As you can see, I used EventTriggerBehavior and the event's name is SelectionChanged.

WP8, DoubleAnimation - "Cannot resolve TargetName" exception

I want to create marquee effect in WP8 application.
To accomplish this I placed StackPanel inside ScrollViewer and I'm trying to use DoubleAnimation on TranslateTransform.X property.
Code:
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name="Scroll" RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimation From="0" To="100" Storyboard.TargetName="transform" Storyboard.TargetProperty="X" Duration="0:0:5" />
</Storyboard>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot">
...
<ScrollViewer Height="80" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden">
<StackPanel Orientation="Horizontal">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="transform" />
</StackPanel.RenderTransform>
<Image Source="/Assets/logo1.png"></Image>
<Image Source="/Assets/logo2.png"></Image>
<Image Source="/Assets/logo3.png"></Image>
<Image Source="/Assets/logo4.png"></Image>
<Image Source="/Assets/logo5.png"></Image>
</StackPanel>
</ScrollViewer>
</Grid>
Unfortunately when calling Scroll.Begin() from code-behind in page Loaded event handler I'm getting exception: System.InvalidOperationException: Cannot resolve TargetName transform.
What I'am doing wrong?
Animation runs when I place StackPanel directly in LayoutRoot but not when it's child of ScrollViewer.
I think the exception is explanatory. Like you apply storyboard on some UI element but there is no element named "transform" in your xaml to which this storyboard will be going to be applied.
so this property Storyboard.TargetName should be name of the UI element that has to be transformed.
In your case if you have to simply give your StackPanel a name say MyStackPanel and then put this name in place of transform in your storyboard code.
<StackPanel Orientation="Horizontal" Name="MyStackPanel">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="transform" />
</StackPanel.RenderTransform>
...
You storyboard should be changedin this way..
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name="Scroll" RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimation From="0" To="100" Storyboard.TargetName="MyStackPanel" Storyboard.TargetProperty="X" Duration="0:0:5" />
</Storyboard>
</phone:PhoneApplicationPage.Resources>
Important :-It would be much better if you just use Blend for making a simple animation and then see how the animation code generated in the page Xaml. You will got all of your answers :)

How to create and show popups from ViewModel

First of I should apologize if the question seems to look simple however I'm new to WPF and MVVM and I really don't know how to do the job.
What I need is to show popups from ViewModel. I know I can have a boolean property in the viewModel and bind it to the IsOpen property of the Popup but I don't know where to create this popup window.
I have some views and each view has to display certain popup messages depending on different situations. Now I need to know whether I should create several popups in each view and bind their IsOpen property to that of in the ViewModel or there are better solutions, and if I should create them in the view, where to put them? In a grid, in a StackPanel or anywhere else.
please let me know if I haven't explained clearly. Any help is appreciated.
I usually have a Third object to control my popup's and dialog , like Caliburn's WindowManager
WindowManager
Witch takes a ViewModel as Content and Displays it's Corresponding View in the Popup.
You can do something similar and Bind a Content from your ViewModel to your popup or Dialog.
For Instance , here's an a Custom Action i created for such a purpose :
OpenPopupWindowAction
this is sample popup. reference
basic popup msdn overview
<StackPanel>
<CheckBox Name="PCheckBox" Margin="10,10,0,0"
Content="Popup Window"/>
<Button HorizontalAlignment="Left" Width="129" Margin="10,10,0,0">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="theTransform"
Storyboard.TargetProperty="(RotateTransform.Angle)"
From="0" To="360" Duration="0:0:5" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
Start Animation
</Button>
<Popup IsOpen="{Binding ElementName=PCheckBox,Path=IsChecked}"
PlacementTarget="{Binding ElementName=PCheckBox}"
AllowsTransparency="True"
PopupAnimation="Slide"
HorizontalOffset="150"
VerticalOffset="100"
>
<Canvas Width="100" Height="100" Background="Green" Margin="150">
<Canvas.RenderTransform>
<RotateTransform x:Name="theTransform" />
</Canvas.RenderTransform>
<TextBlock TextWrapping="Wrap" Foreground="LightGray">
Rotating Popup
</TextBlock>
</Canvas>
</Popup>
private void OnPopupLoaded(object sender, RoutedEventArgs e)
{
this.ParentPopup.HorizontalOffset = (Window.Current.Bounds.Width - gdChild.ActualWidth) / 2;
this.ParentPopup.VerticalOffset = (Window.Current.Bounds.Height - gdChild.ActualHeight) / 2;
}

WPF C# : Label not big enough

I am using WPF for my C# application on which i have several labels in which the texts don't fit. What I want is to make my text move inside the label so that the user can see the entire text.
Example : let's say that my text is 20 characters long, by my label has enough space for only 15 characters. What I want is that my label to display the first 15 characters (characters 1-15) then after 1 second the same characters without the first but with another at the end (so characters 2-16) then the next (characters 3-17) and so on until the last 15 characters (characters 5-20) and then I want them to start from the beginning (the characters 1-15 again).
How can I do that ? One way is (obviously) to use a Timer, but I am sure that a more elegant solution exists.
Below is code for a quick-and-dirty scrolling control that should do what you want as soon as the user mouses over the control.
<Canvas Name="brd"
ClipToBounds="True"
Margin="10"
Height="20" Width="150"
Background="White"
HorizontalAlignment="Left">
<StackPanel Name="spl1"
Orientation="Horizontal"
Canvas.Left="0">
<TextBlock Name="tbk1"
Margin="10,0"
MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
Text="A display of test text that is wider than the control."/>
<TextBlock MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
Margin="10,0"
Text="{Binding ElementName=tbk1,Path=Text}"/>
</StackPanel>
<Canvas.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Name="scroll">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation To="-200" Duration="0:0:4"
Storyboard.TargetName="spl1"
Storyboard.TargetProperty="(Canvas.Left)" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<StopStoryboard BeginStoryboardName="scroll"/>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
There is one part that you will need to change for proper operation, that I did not implement. The <DoubleAnimation To="-200"... will need to be changed. Ideally the value for To will be the negative of the ActualWidth property of the tbk1 control. This will require both an element binding to get the value and a ValueConverter to make that value negative.
If you don't want to go to the trouble of a converter, you can just make the To value sufficiently large to accommodate the longest text that you expect. That will get you reasonably close.
You can, of course, tweak this more to provide a smoother transition at the end of one animation cycle and the start of the next.
EDIT
OK, I couldn't leave it half finished. Below is the updated XAML for smooth operation, and the included code for the ValueConverter.
<Window.Resources>
<Converters:ChangeSignConverter x:Key="ChangeSignConverter"/>
</Window.Resources>
<Canvas Name="brd"
ClipToBounds="True"
Margin="10"
Height="20" Width="150"
Background="White"
HorizontalAlignment="Left">
<StackPanel Name="spl1"
Margin="5,0,0,0"
Orientation="Horizontal"
Canvas.Left="0">
<TextBlock Name="tbk1"
Padding="0,0,10,0"
MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
Text="A display of test text that is wider than the control."/>
<TextBlock MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
Text="{Binding ElementName=tbk1,Path=Text}"/>
</StackPanel>
<Canvas.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Name="scroll">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation To="{Binding ElementName=tbk1,Path=ActualWidth,Converter={StaticResource ChangeSignConverter}}"
Duration="0:0:4"
Storyboard.TargetName="spl1"
Storyboard.TargetProperty="(Canvas.Left)" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<StopStoryboard BeginStoryboardName="scroll"/>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
Converter class:
class ChangeSignConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Convert.ToDouble(value) * -1;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Convert.ToDouble(value) * -1;
}
}
You could also use the WPF animation functionality. You create a custom control which has a TextBlock inside. Define the control's width (which would be smaller than the textblock's width. Then define the storyboard and double animation to animate it however you want it (slower / faster, only animate to the right, animate right then left and so on).
This is just an idea. I'm currently in a rush, but I can provide you with additional code, if you need it.
I would also use Timer for functionality you described. I think there are not many other solutions, if you insist on changing Label in some specified time interval. On the other hand, I would probably use ToolTip, which I think is more intuitive for this.

Checkbox triggers stackpanel expand/collapse animation

I have WP7 application with simple phone page.
I have check box
<CheckBox Content="Click me" Margin="0,2,0,0">
When I check the checkbox I want Stack panel below it to expand.
<StackPanel Height="0" x:Name="MyStackPanel">
<CheckBox Content="Condition"/>
</StackPanel>
Right now I tried this solution, but i receive exception that EventTrigger.RoutedEvent cannot be assign to Checkbox.Checked.
<CheckBox Content="Click Me" Margin="0,2,0,0">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyStackPanel"
Storyboard.TargetProperty="Height"
To="100"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
Do you have any ideas what is the best approach to implement such animation?
Thanks
There is a control for what you require to do. You should be using the Expander control that iss part of the silverlight toolkit . There iS A good two part tutorial about working with this control here on WindowsPhoneGeek.
Basically, you use the expander control and implement your own custom controls for the header and the items.
try ToggleButton.Checked instead of CheckBox.Checked

Categories