Сразу предупреждаю, этот пример я писал на коленке, в нем нужно сделать проверки на значения которые передаются в AttachedProperty, так как они могут быть пустыми и сделать соответствующую логику на этот случай
Так же важно (необходим) для Storyboard для анимации До! указать длительность этой анимации
И так же важно учесть тот факт, что свойство будет удерживаться анимацией, то есть поменять его можно будет только прекратив анимацию.
Но надеюсь данного примера будет достаточно. В примере элемент ContentControl скрывается, у него меняется свойство Content и затем появляется, код в принципе универсальный :) удачи
Тестовая модель представления:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
public class Person
{
private readonly string _name;
private readonly int _age;
public Person(string name, int age)
{
_name = name;
_age = age;
}
public string Name { get { return _name; } }
public int Age { get { return _age; } }
}
public class MainModel : INotifyPropertyChanged
{
private List<Person> _persones;
private int _personNumber;
private Person _currentPerson;
private List<Person> Persones
{
get
{
return _persones ?? (_persones = new List<Person>(GetPersones()));
}
}
private IEnumerable<Person> GetPersones()
{
yield return new Person("Roman", 31);
yield return new Person("Sofia", 36);
yield return new Person("Olga", 6);
yield return new Person("Sasha", 14);
}
public Person CurrentPerson
{
private set
{
if (Equals(value, _currentPerson)) return;
_currentPerson = value;
OnPropertyChanged();
}
get { return _currentPerson; }
}
public int PersonNumber
{
set
{
_personNumber = value;
CurrentPerson = Persones[_personNumber];
}
get { return _personNumber; }
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Окно:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
<Window x:Class="WpfApplication47.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication47"
Title="MainWindow" Height="350" Width="525"
DataContext="{StaticResource MainModel}">
<Window.Resources>
<DataTemplate x:Key="{x:Type local:Person}" DataType="{x:Type local:Person}">
<StackPanel>
<TextBlock Text="Name:"/>
<TextBlock Text="{Binding Name}" Foreground="DarkBlue"/>
<TextBlock Text="Age:"/>
<TextBlock Text="{Binding Age}" Foreground="DarkGreen"/>
</StackPanel>
</DataTemplate>
<Storyboard x:Key="AfterAnimation" Duration="0:0:.5">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:.5"/>
</Storyboard>
<Storyboard x:Key="BeforAnimation" Duration="0:0:.5">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:.5"/>
</Storyboard>
</Window.Resources>
<DockPanel >
<Slider Minimum="0" Maximum="3" DockPanel.Dock="Top" Margin="5"
Value="{Binding PersonNumber}"></Slider>
<ContentControl ContentTemplate="{StaticResource {x:Type local:Person}}"
HorizontalAlignment="Center" VerticalAlignment="Center"
local:AnimationValueChanger.AfterStoryboard="{StaticResource AfterAnimation}"
local:AnimationValueChanger.BeforeStoryboard="{StaticResource BeforAnimation}"
local:AnimationValueChanger.Value="{Binding CurrentPerson}"
local:AnimationValueChanger.PropertyTarget="Content" />
</DockPanel>
</Window>
local:AnimationValueChanger:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
public class AnimationValueChanger
{
public static Storyboard GetAfterStoryboard(DependencyObject obj) { return (Storyboard)obj.GetValue(AfterStoryboardProperty); }
public static void SetAfterStoryboard(DependencyObject obj, Storyboard value) { obj.SetValue(AfterStoryboardProperty, value); }
public static readonly DependencyProperty AfterStoryboardProperty =
DependencyProperty.RegisterAttached("AfterStoryboard", typeof(Storyboard), typeof(AnimationValueChanger), new PropertyMetadata(null));
public static Storyboard GetBeforeStoryboard(DependencyObject obj)
{
return (Storyboard)obj.GetValue(BeforeStoryboardProperty);
}
public static void SetBeforeStoryboard(DependencyObject obj, Storyboard value)
{
obj.SetValue(BeforeStoryboardProperty, value);
}
public static readonly DependencyProperty BeforeStoryboardProperty =
DependencyProperty.RegisterAttached("BeforeStoryboard", typeof(Storyboard), typeof(AnimationValueChanger), new PropertyMetadata(null));
public static PropertyPath GetPropertyTarget(DependencyObject obj)
{
return (PropertyPath)obj.GetValue(PropertyTargetProperty);
}
public static void SetPropertyTarget(DependencyObject obj, PropertyPath value)
{
obj.SetValue(PropertyTargetProperty, value);
}
public static readonly DependencyProperty PropertyTargetProperty =
DependencyProperty.RegisterAttached("PropertyTarget", typeof(PropertyPath), typeof(AnimationValueChanger), new PropertyMetadata(null));
public static object GetValue(DependencyObject obj) { return obj.GetValue(ValueProperty); }
public static void SetValue(DependencyObject obj, object value) { obj.SetValue(ValueProperty, value); }
public static readonly DependencyProperty ValueProperty =
DependencyProperty.RegisterAttached("Value", typeof(object), typeof(AnimationValueChanger), new FrameworkPropertyMetadata(null, OnContentChanged));
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var afterStoryboard = GetAfterStoryboard(d);
var beforeStoryboard = GetBeforeStoryboard(d);
var propertyPath = GetPropertyTarget(d);
var content = e.NewValue;
if (afterStoryboard == null)
{
d.SetValue(ContentPresenter.ContentProperty, content);
}
else
{
var setter = new ObjectAnimationUsingKeyFrames
{
KeyFrames =
{
new DiscreteObjectKeyFrame
{
KeyTime = afterStoryboard.Duration.TimeSpan,
Value = content
}
}
};
Storyboard.SetTargetProperty(setter, propertyPath);
var totalStoryBoard = new Storyboard();
beforeStoryboard.BeginTime = afterStoryboard.Duration.TimeSpan;
totalStoryBoard.Children.Add(afterStoryboard);
totalStoryBoard.Children.Add(setter);
totalStoryBoard.Children.Add(beforeStoryboard);
totalStoryBoard.Begin((FrameworkElement)d);
}
}
}