У меня есть групповые ящики, действующие как расширители в моем приложении. Когда мне нужно свернуть групповой ящик, я устанавливаю его высоту равной 0. когда мне нужно его расширить, я устанавливаю его высоту, равную auto (double.Nan), можно ли сделать это с помощью раскадровки. Откуда я мог знать высоту авто заранее. Комбинация выражений не позволяет мне анимировать авто.
Анимировать высоту группового поля от 0 до авто
Ответы (3)
Вы можете использовать ScaleTransform для этого
<GroupBox Header="GroupBox">
<GroupBox.RenderTransform>
<ScaleTransform ScaleY="1"/>
</GroupBox.RenderTransform>
</GroupBox>
При сворачивании группового поля установите для ScaleTransform.ScaleX значение 0. При расширении установите значение 1.
Поскольку я ненавижу трансформацию масштаба, потому что считаю ее уродливой, я искал другое решение.
Что ж, я знаю, что это старый пост и существует множество обходных путей, но мой довольно прост, и я не читал его нигде, даже если кто-то точно его нашел.
Вместо анимации высоты от X до Auto
(что невозможно), вы можете сделать высоту равной Auto
и анимировать свойство MaxHeight
:
<MyControl x:Name="ctrlAutoHeight" Height="Auto">
<MyControl.Triggers>
<EventTrigger RoutedEvent="myRoutedEvent">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ctrlAutoHeight"
Storyboard.TargetProperty="MaxHeight"
From="0.0"
To="{Binding ElementName=ParentControl, Path=ActualHeight}"
Duration="0:0:1"
AutoReverse="False"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</MyControl.Triggers>
</MyControl>
To
к MaxHeight моего окна или к его сетке.
- person Kilazur; 26.01.2015
binding
в анимации? Почему вы можете это сделать? stackoverflow.com/a/154227/3907561
- person Joke Huang; 31.03.2021
Вот готовый к использованию пример, основанный на StackPanel (не стесняйтесь заменить его на GroupBox).
Для тех, у кого есть «InvalidOperationException: невозможно заморозить это дерево временной шкалы раскадровки для использования между потоками», это исключение возникает, когда привязка определена внутри раскадровки, которая сама определена внутри ControlTemplate или Style. В некотором смысле замороженная анимация — это анимация, в которой все значения статичны (скажем, предварительно рассчитаны).
Просто чтобы почувствовать проблему, представьте, что в StackPanel добавляются или удаляются некоторые элементы управления во время анимации, теоретически для успешного выполнения этой анимации механизм анимации должен учитывать эти изменения (через привязки), но, к сожалению, WPF на самом деле этого не делает. поддержите это дело.
Чтобы вернуться к приведенному ниже решению, обратите внимание, что я использую привязки вне какого-либо ControlTemplate или Style. В этом случае параметры анимации вычисляются при запуске событий, но после воспроизведения они не обновляются при изменении связанных свойств.
Следовательно, это решение (если не другие) страдает от 2 неблокирующих проблем:
- В конце анимации размер StackPanel может быть неправильным, если содержимое StackPanel изменяется во время анимации.
- При быстром щелчке несколько раз по флажку продолжительность анимации всегда будет одинаковой независимо от оставшегося пространства для свертывания или расширения.
<StackPanel>
<!-- CheckBox used for triggering the StackPanel animation -->
<CheckBox Content="Expand/Collapse">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<!-- Expand animation -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="StackPanel"
Storyboard.TargetProperty="Height"
From="{Binding ElementName=StackPanel, Path=Height}"
To="{Binding ElementName=ContentSize, Path=DesiredSize.Height}"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="CheckBox.Unchecked">
<!-- Collapse animation -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="StackPanel"
Storyboard.TargetProperty="Height"
From="{Binding ElementName=StackPanel, Path=Height}"
To="0"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
<!-- The animated StackPanel -->
<StackPanel x:Name="StackPanel" Height="0">
<!-- The border below acts as a probe to get the expected StackPanel container size -->
<Border x:Name="ContentSize">
<TextBlock>Some Content</TextBlock>
</Border>
</StackPanel>
</StackPanel>
До сих пор кажется, что идеального и простого решения этой проблемы не существует...