<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
ButtonHoverBackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
ButtonHoverBorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetProperty="Foreground"
Storyboard.TargetName="ContentControl">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
LightForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
Instead of going Storyboard.TargetName=ContentControl and Storyboard.TargetProperty=Foreground,
i would like to Animate the templated parent's foreground, and the content control to just have it's foreground property binded to the templated parent
Foreground={TemplateBinding Foreground}
The reason for this is that when i use the control with this template, i want to be able to do :
<Button Width="125"
Height="30"
Click="OnButtonClick"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="50,54,0,0">
<Button.Content>
<controls:SomeCustomControl '
Foreground="{Binding Path=Foreground,
RelativeSource={RelativeSource AncestorType=
{x:Type Button}}}" />
</Button.Content>
</Button>
I tried doing :
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.Target="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource LightForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
however this crashes.
Any suggestions on how this can be done? Thanks in advance.
Same Problem on my Side ....
But it could be that we just thought in the wrong way.
It is "Content" to be styled but no one knows what Content it would be. So the "right" way would be to say that its the work for the Control you put into the Content.
Example, if you put a Button into a ContentControl, the Button style handle the VSM not the ContentControl around it.
That ist not the exactly answer to your question but maybe some help to understand why this isnĀ“t some option.
Edit:
After some research i found this:
Animating a TextBox.Foreground in WPF
It feels not the best practice but it could be work for your problem.
I have a ControlTemplate which targets a button control. The ControlTemplate has two images for the normal and pressed states, one for each. I want to use this ControlTemplate in 8 different buttons in the screen, each one with a diferent image in front of it.
<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates1">
<VisualState x:Name="Pressed1">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal1"/>
<VisualState x:Name="Disabled1"/>
<VisualState x:Name="MouseOver1"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates1">
<VisualState x:Name="Focused1"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates"/>
<VisualStateGroup x:Name="FocusStates"/>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image" Source="source1" />
<Image x:Name="image1" Source="source2" Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
How can I put a third image inside the template that can receive a different source for each button?
Something like this:
<Button Template="{StaticResource ButtonControlTemplate1}" thirdImage="source_to_third_image"/>
Why not just use the Content property for your third image?
Your ControlTemplate will look like this:
<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="Button">
<Grid>
...
<ContentPresenter Content="{TemplateBinding Content}" />
<Image x:Name="image" Source="source1" />
<Image x:Name="image1" Source="source2" Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
And your button declaration will look like this:
<Button>
<Image Source="source3" />
</Button>
Then you just need to add a relevant visual state.
From what I understand in your question, you're looking to implement attached properties.
Since the button itself does not carry properties for three separate image sources (you could hack around the Content property, but that would be a pain), you will need to implement those and simply perform standard binding from your template.
I have a grid containing two elements, a search form and a custom UC to show items. When my page loads, the viewer control is hidden. I ant to animate it in with a storyboard when a button on the search form is clicked. I'm stuck at the To=... part of the animation. I want to animate it to the height of the parent container and have it slid up from the bottom. Is this possible?
For reference, this is my tree structure:
Page resources:
<Storyboard x:Name="animateViewSlide" Storyboard.TargetName="SearchForm" >
<DoubleAnimation Storyboard.TargetProperty="Height" To="???" Duration="100"/>
</Storyboard>
Control body:
<Grid x:Name="LayoutRoot">
<Grid x:Name="SearchForm" Margin="6,6,6,70">
<uc:AwesomeViewer x:Name="awesomeView" Awesomeness="{Binding SelectedAwesomeThing}" Visibility="Collapsed"/>
</Grid>
UPDATE
I did figure out a bit better way of doing this, instead of using the Margin to step through the animation, just animate the Y axis with a TranslateTransform like;
<Grid x:Name="ItemToMove"
Visibility="{Binding Condition, Converter={StaticResource boolVisConv}}" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="30,0,0,-32" Opacity="0">
<Grid.RenderTransform>
<TranslateTransform x:Name="notified" Y="40" />
</Grid.RenderTransform>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="notified" Storyboard.TargetProperty="Y">
<SplineDoubleKeyFrame KeyTime="0:0:1.25" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ItemToMove" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0:0:1.55" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
END UPDATE
Your trouble is going to stem from trying to animate an automatically calculated value (Height) so I would scrap that idea unless you want to use hard coded size values on your Parents/Children or just assume for example that if the app is restricted to Portrait Mode only....then your "To" value is 800px, except I imagine that's not what you're looking for.
Now then, you would usually hope you could just feed the rendered size into your "To" value, like maybe via To="{Binding ActualHeight, ElementName=LayoutRootOROTHERParentContainer}" right? Yet nay, that won't work either...
So while someone else may have a better way, the only way I've found is to instead leave the Auto calculated sizes alone to do their thing, and instead animate a stepping of the object Margin via ObjectAnimationUsingKeyFrames which when paired with an Opacity transition via DoubleAnimationUsingKeyFrames actually looks quite nice, except it will add a bunch of additional XAML for the process. So as a concept you might try something more like this (however if you come across a better solution, I'd sure like to know it also. As a designer for a living, I run into this relatively often.)
Concept Example;
(The Storyboard)
<Storyboard x:Name="Kaboom">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0:0:0.1">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,750,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,600,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,550,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,500,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,450,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.6">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,400,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.7">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,350,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.8">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,300,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.9">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,250,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,200,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1.1">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,150,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1.2">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,100,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1.3">
<DiscreteObjectKeyFrame.Value>
<Thickness>0,50,0,0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1.4">
<DiscreteObjectKeyFrame.Value>
<Thickness>0</Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border">
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="0.01"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.6" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
A quick adhoc example of the concept in action;
<Grid Height="800" Width="480" x:Name="ParentContainer">
<!-- Your SearchForm thingy with its funky margins already set like your example -->
<Rectangle Margin="6,6,6,70" Fill="Green" />
<Button Height="100" Width="100" Content="Click Me!" HorizontalAlignment="Left" VerticalAlignment="Top">
<!-- Quick button to show it in action -->
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ControlStoryboardAction Storyboard="{StaticResource Kaboom}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<!-- Your Awesomeness -->
<Border x:Name="border" Width="300" Background="Blue" HorizontalAlignment="Right" Margin="0,800,0,0" Opacity="0">
<TextBlock x:Name="textBlock" Text="OH
SNAP!!!
Say
WHAAA??"
TextAlignment="Center" VerticalAlignment="Center"
FontSize="40" FontWeight="Bold" Foreground="White"/>
</Border>
</Grid>
Anyway, probably not exactly what you're hoping for, but is an effective alternative especially with a little tweaking unless like I said, you want to hardcode your object sizes so you have something viable to set your "To" value to...which, in the case of a phone that's restricted to the standard 800x480 Portrait Mode Only you may very well want to. However if you don't have that option, I've pulled off some pretty nifty designs using this method instead.
Hope this helps and best of luck!
My Code is posted Below. I am creating an image, and attempting to add animation to it. I am sure it was working at one point, I made a small change, it failed I undid the change (literally undo) and now it continues to fail. I am attempting to make an image change ever half second to another image, then change back after another half second.
<Image Height="30" HorizontalAlignment="Left" Margin="198,90,0,0" Name="OldMan" Stretch="Fill" VerticalAlignment="Top" Width="30" Source="/TestingWpF;component/Images/Old1.png" >
<Image.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OldMan" Storyboard.TargetProperty="(Image.Source)" RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="00:00:00.5000000">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="/TestingWpF;component/Images/Old1.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="00:00:01.0000000">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="/TestingWpF;component/Images/Old2.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
The problem is that you don't have your duration set. You'll just get the first keyframe, but not the next. Try adding something like Duration="00:00:01.5" to ObjectAnimationUsingKeyFrames
i want to be able to change the tooltip on Checked and Unchecked, i tried:
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="ToolTipService.ToolTip" Storyboard.TargetName="btn">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:String>Button is checked</System:String>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
but it doesnt seem to work, what am i doing wrong?
Once before I also, ran into the same problem. So, I left the VSM away. I made the ToolTip as Resource and applied it for the control. Using the internal state change properties I updated the tooltip value using a converter.
HTH.