Скажем, у нас есть код XAML как это:
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center">
<Border.LayoutTransform>
<!--We are rotating randomly each image. Selected one will be rotated to 45°.-->
<RotateTransform Angle="{Binding RandomAngle}" x:Name="globalRotation"/>
</Border.LayoutTransform>
<Grid>
<Image Source="{Binding ImageLocation}" Stretch="None" />
<TextBlock x:Name="title" Text="{Binding Title}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="title" Property="Visibility" Value="Visible"/>
<!--The next line will not compile.-->
<Setter TargetName="globalRotation" Property="Angle" Value="45"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!--This compiles well.-->
<DoubleAnimation Storyboard.TargetName="globalRotation" Storyboard.TargetProperty="Angle" To="45" Duration="00:00:03"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Этот код предназначается для отображения ряда изображений в поле списка. Каждое изображение имеет случайное вращение, но при выборе вращается до 45 градусов.
Вращение выбранного изображения через раскадровку работает хорошо. Я просто указываю Storyboard.TargetName
и это поворачивает изображение при выборе (Trigger.ExitActions
опущен для создания кода короче).
Теперь, если я хочу, вместо того, чтобы использовать раскадровку, присваиваю значение на 45 градусов непосредственно, я не могу сделать этого, потому что <Setter TargetName="globalRotation" Property="Angle" Value="45"/>
: это компилирует с
"Не может найти, что Триггер предназначается для 'globalRotation'. (Цель должна появиться перед любыми Методами set, Триггерами или Условиями, которые используют ее.)"
ошибка. Что происходит? Я предполагаю это Storyboard.TargetName
оценен во время времени выполнения, таким образом позвольте мне скомпилировать его. Действительно ли это правильно?
Как заставить его работать только с методом set, не используя раскадровку?
Дело в том, что Trigger Setter может быть нацелен только на объекты FrameworkElement или FrameworkContentElement, тогда как Storyboard работает с любым DependencyProperty.
Вот обходной путь:
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="brd" HorizontalAlignment="Center" VerticalAlignment="Center" Tag="{Binding RandomAngle}">
<Border.LayoutTransform>
<!--We are rotating randomly each image. Selected one will be rotated to 45°.-->
<RotateTransform Angle="{Binding ElementName=brd, Path=Tag}" x:Name="globalRotation"/>
</Border.LayoutTransform>
<Grid>
<Image Source="{Binding ImageLocation}" Stretch="None" />
<TextBlock x:Name="title" Text="{Binding Title}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="title" Property="Visibility" Value="Visible"/>
<!--The next line will not compile.-->
<Setter TargetName="brd" Property="Tag" Value="45"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!--This compiles well.-->
<DoubleAnimation Storyboard.TargetName="globalRotation" Storyboard.TargetProperty="Angle" To="45" Duration="00:00:03"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>