The sample code for this article includes a little program called ButtonSetAndAnimate
that doesn’t do anything particularly useful except to illustrate how
animation fits into dependency property precedence.
The XAML file contains a Slider with a range of 0 to 100, a TextBlock showing the Slider value, and four buttons:
Example 1. Silverlight Project: ButtonSetAndAnimate File: MainPage.xaml (excerpt)
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding ElementName=slider, Path=Value}" HorizontalAlignment="Center" Margin="24" />
<Slider Name="slider" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Minimum="0" Maximum="100" Orientation="Horizontal" VerticalAlignment="Center" />
<Button Grid.Row="2" Grid.Column="0" Content="Set to 0" Click="OnSetToZeroClick" />
<Button Grid.Row="2" Grid.Column="1" Content="Set to 100" Click="OnSetToOneHundredClick" />
<Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Animate to 50" HorizontalAlignment="Center" Click="OnAnimateTo50Click" />
<Button Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Content="Set Maximum to 25" HorizontalAlignment="Center" Click="OnSetMaxTo40Click" /> </Grid>
|
Also in the XAML file is an animation that targets the Value property of the Slider.
Example 2. Silverlight Project: ButtonSetAndAnimate File: MainPage.xaml (excerpt)
<phone:PhoneApplicationPage.Resources> <Storyboard x:Name="storyboard"> <DoubleAnimation Storyboard.TargetName="slider" Storyboard.TargetProperty="Value" To="50" Duration="0:0:5" /> </Storyboard> </phone:PhoneApplicationPage.Resources>
|
Handlers for the four buttons are in the code-behind file:
Example 3. Silverlight Project: ButtonSetAndAnimate File: MainPage.xaml.cs (excerpt)
public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); }
void OnSetToZeroClick(object sender, RoutedEventArgs args) { slider.Value = 0; }
void OnSetToOneHundredClick(object sender, RoutedEventArgs args) { slider.Value = 100; }
void OnAnimateTo50Click(object sender, RoutedEventArgs args) { storyboard.Begin(); }
void OnSetMaxTo40Click(object sender, RoutedEventArgs e) { slider.Maximum = 25; } }
|
Here’s the program:
You can manipulate the Slider with your finger and you can also use the topmost two buttons to set the Slider value to its minimum or maximum. So far, so good. Now click the “Animate to 50” button.
As the Slider
is animated and moving to the center position, try overriding that
movement with your finger or by pressing the “Set to 0” or “Set to 100”
buttons. You can’t do it. The animation has precedence over local settings, which means that the chart of dependency property precedencemust be supplemented by putting animations at the very top:
Animations have precedence over
Local Settings which have precedence over
Style Settings, which have precedence over the
Theme Style, which has precedence over
Property Inheritance, which has precedence over
Default Values
This is as it should
be. Animations must have precedence over local settings or they wouldn’t
work on properties that are simply initialized to some value.
After the animation has concluded, you’ll discover that you can now manipulate the Slider
both manually and with the first two buttons. This behavior is not
correct and not in accordance with documentation. With the default FillBehavior setting of HoldEnd, the Slider should actually be frozen after the animation has concluded. The Slider should continue to reflect the final value of the animation.
Is there something more
powerful than animations? Yes there is, but it’s probably not something
you’d immediately consider, and you probably won’t find any examples
outside the realm of Slider and ScrollBar.
Set the Slider to its maximum value, and press the “Animate to 50” button again. As the Slider is approaching 50, click the “Set Maximum to 25” button. That sets the Maximum property of the Slider
to 25 and immediately halts the animation. And once again, it seems
logical. No matter what an animation does, it makes no sense whatsoever
for a Slider to have a Value that is outside the range of Minimum and Maximum. This is an example of property coercion:
Property Coercion has precedence over
Animations which have precedence over
Local Settings which have precedence over
Style Settings, which have precedence over the
Theme Style, which has precedence over
Property Inheritance, which has precedence over
Default Values
In theory, values of
templated properties also fit into this chart between local settings and
style settings, but these are hard to differentiate, so this is the
final version of this chart in this book.