У меня есть присоединенное поведение, которое имеет одно присоединенное свойство типа StoryBoard
. Я хочу установить это свойство для каждого элемента в ListView. XAML выглядит примерно так:
<Grid>
<Grid.Resources>
<Storyboard x:Key="TheAnimation" x:Shared="False">
<DoubleAnimation From="0.0" To="1.0" Duration="0:0:0.20"
Storyboard.TargetProperty="Opacity" />
</Storyboard>
</Grid.Resources>
<ListView>
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="local:MyBehavior.Animation"
Value="{StaticResource TheAnimation}" />
</Style>
</ListView.Resources>
</ListView>
</Grid>
Все идет нормально. Затем код в «MyBehavior» пытается сделать это:
private static void AnimationChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var listViewItem = d as ListViewItem;
if (d == null)
return;
var sb = e.NewValue as Storyboard;
if (sb == null)
return;
Storyboard.SetTarget(sb, listViewItem);
sb.Begin();
}
Но при вызове StoryBoard.SetTarget()
выдается InvalidOperationException
: «Невозможно установить свойство для объекта« System.Windows.Media.Animation.Storyboard », поскольку он находится в состоянии только для чтения». Если я проверю Storyboard
в отладчике, я увижу, что оба его свойства IsSealed
и IsFrozen
установлены на true
.
Напротив, если я устанавливаю MyBehavior.Animation
непосредственно на ListView
, чтобы мне не нужно было использовать Style
, StoryBoard
прибывает незапечатанным, и я могу установить цель и успешно запустить ее. Но это не то, чего я хочу.
Почему мой StoryBoard
запечатан, и могу ли я что-нибудь сделать, чтобы предотвратить это?
Обновление: я могу решить свою проблему, добавив это сразу после нулевой проверки:
if(sb.IsSealed)
sb = sb.Clone();
Но мне все равно интересно, что происходит. Видимо что-то где-то (Style
? Setter
?) замораживает/запечатывает объект в Setter.Value
.
Style
предположительно преобразуется в один объектStyle
. Этот единственный объект вместе сValue
объектами в егоSetter
s потенциально может использоваться совместно несколькими объектами. Поэтому, если один из них каким-то образом перехватит объектValue
(в моем случае этоPropertyChangedCalledback
) и изменит его, это непреднамеренно повлияет на все другие объекты, которые разделяют этот стиль. Разработчики фреймворка предвидели это и запечаталиValue
, чтобы этого не произошло. Это мое предположение, по крайней мере. - person dlf   schedule 18.07.2015