WPF: Добавить анимацию через встроенный в элемент стиль?

Вопрос к знатокам.

У меня есть Expander.

Я добавил к нему стиль, в котором определил анимацию для свертывания/развертывания содержимого (Content):
<Expander>
...
<Expander.Style>
	<Style>
		<Setter Property="Expander.BorderBrush" Value="LightBlue" />
		<Setter Property="Expander.BorderThickness" Value="1" />
		<Style.Triggers>
			<Trigger Property="Expander.IsExpanded" Value="True">
				<Trigger.EnterActions>
					<BeginStoryboard>
						<Storyboard>
							<DoubleAnimation From="0" Duration="0:0:0.2" Storyboard.TargetProperty="Content.Height" />
						</Storyboard>
					</BeginStoryboard>
				</Trigger.EnterActions>
				<Trigger.ExitActions>
					<BeginStoryboard>
						<Storyboard>
							<DoubleAnimation To="0" Duration="0:0:0.2" Storyboard.TargetProperty="Content.Height" />
						</Storyboard>
					</BeginStoryboard>
				</Trigger.ExitActions>
			</Trigger>
		</Style.Triggers>
	</Style>
</Expander.Style>
</Expander>


Содержимое плавно разворачивается.

Теперь о проблемах:

1. Содержимое плавно не сворачивается.

2. Хочется чтобы стрелочка на кнопке крутилась на 180 градусов, согласно примеру:

<ControlTemplate.Triggers>
    <!-- Animate arrow when toggled-->
    <Trigger Property="IsChecked"
             Value="True">
        <Trigger.EnterActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="Arrow"
                         Storyboard.TargetProperty=
                           "(Path.RenderTransform).(RotateTransform.Angle)"
                         To="180"
                         Duration="0:0:0.4"/>
                </Storyboard>
            </BeginStoryboard>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="Arrow"
                         Storyboard.TargetProperty=
                           "(Path.RenderTransform).(RotateTransform.Angle)"
                         To="0"
                         Duration="0:0:0.4"/>
                </Storyboard>
            </BeginStoryboard>
        </Trigger.ExitActions>
    </Trigger>
</ControlTemplate.Triggers>



т.е. изменить первоначальный код на этот:
<Expander.Style>
    <Style>
        <Setter Property="Expander.BorderBrush" Value="LightBlue" />
        <Setter Property="Expander.BorderThickness" Value="1" />
        <Style.Triggers>
            <Trigger Property="Expander.IsExpanded" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation From="0" Duration="0:0:0.2" Storyboard.TargetProperty="Content.Height" />
                            <DoubleAnimation Storyboard.TargetName="Arrow" Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)" To="180" Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="0" Duration="0:0:0.2" Storyboard.TargetProperty="Content.Height" />
                            <DoubleAnimation Storyboard.TargetName="Arrow" Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)" To="0" Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
        </Style.Triggers>
    </Style>
</Expander.Style>


Но, как вы понимаете. Этот код не работает. Подскажите пожалуйста, что здесь не так?


Навеяно этой статьей.
  • Вопрос задан
  • 5428 просмотров
Решения вопроса 1
@Paulskit
Лучше сразу делать правильно.
1) Ваш подход с Content.Height неверен. Если Height не задан, то есть равен NaN, получим RuntimeException.
2) Вместо того, чтобы писать стиль внутрь элемента сохраните его в Resources для данного окна/страницы.
3) Переопределите ContentTemplate, чтобы анимация работала для всех случаев.

Теперь о том, почему не работает.
Изначально всё работает таким образом. Свойство Visibility нашего ContentPresenter установлено в значение Collapsed. Раскрытие производится следующим триггером.
<Trigger Property="IsExpanded" Value="true">
   <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger>


Для того, чтобы исправить ситуацию немного перепишем ControlTemplate.
Для начала удалим свойство Visibility.

После этого, добавим внутрь следующий блок:
<ContentPresenter.LayoutTransform>
   <ScaleTransform ScaleX="1" ScaleY="0"/>
</ContentPresenter.LayoutTransform>


И в завершении, заменим вышеуказанный триггер на эти:
<EventTrigger RoutedEvent="Expander.Expanded">
   <BeginStoryboard>
      <Storyboard Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="LayoutTransform.ScaleY">
          <DoubleAnimation To="1" Duration="0:0:0.2"/>
      </Storyboard>
   </BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Expander.Collapsed">
   <BeginStoryboard>
      <Storyboard Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="LayoutTransform.ScaleY">
          <DoubleAnimation To="0" Duration="0:0:0.2"/>
      </Storyboard>
   </BeginStoryboard>
</EventTrigger>


Пример:
pastebin.com/FmGAVbA5
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
renny
@renny
1) Вы создали триггер только для разворота, поэтому и сворачиваеться без анимации.

Создайте триггер и для
и будет вам счастье

2) у «стрелочки» создайте пустую трансформацию (те без значений) и все заработает
<Стрелочка RenderTransformOrigin=«0.5,0.5»>
<Стрелочка .RenderTransform>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform />

</Стрелочка .RenderTransform>
</Стрелочка >
Ответ написан
NikitaTratorov
@NikitaTratorov Автор вопроса
CTO
У кого-нибудь есть мысли?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы