Пытаюсь сделать binding в xaml c# .net
У меня есть Storyboard и анимация открытия меню, работает так: юзер нажимает на кнопку и подрубается Storyboard, он в свою очередь меняет ширину панель до 240, после юзер захочет закрыть панель и нажмёт на туже кнопку, после чего тот-же Storyboard уменьшит ширину до 40. У сторибоарда есть два значения, на 0 секунде и на 1 секунде, с самого начала я подумал что легче будет поставить два сторибоарда и проблема пропадёт, но нет, есть один минус, если их будет два тогда если юзер захочет закрыть панель до того как она открылась тогда она не поедет назад, а если же поставить binding на эти два сторибоарда тогда это будет намного сложнее чем поставить один сторибоард и сделать ему binding. Ну так вот, получается я хочу сделать к сторибоарду биндинг в c#, когда юзер нажмёт кнопку, программа будет проверять, какая сейчас ширина панели, если 48 тогда вторая точка будет равна 240, если же пользователь уже открывал панель и сейчас он хочет её закрыть, код будет проверять какая ширина панели, если 240 тогда вторая точка будет 48, но есть первая точка о которой я не упоминал. При нажатии на кнопку первая точка будет ставится на текущее значение ширины панели. Сейчас я подумываю о коде такого типа:
<Storyboard x:Key="clientZoneStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="client_zone" Storyboard.TargetProperty="(FrameworkElement.Width)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="{Binding ElementName=client_zone, Path=ActualWidth}">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="{Binding ElementName=client_zone, Path=ActualWidth}">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
весь код пишу в blend'е. Xaml, c#, net core 3.1 сразу благодарен за каждый ответ.
Ответы (1 шт):
Вы как-то делаете слишком сложно с анимацией. Вам нужно просто указать To (но не From!) в анимации «туда», и вообще ничего не указывать в анимации «обратно».
Я попытался набросать в виде контрола, чтобы можно было повторно использовать. Получилось вот что:
<UserControl x:Class="TestApp.CollapsiblePanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard"
xmlns:local="clr-namespace:TestApp">
<UserControl.Template>
<ControlTemplate TargetType="{x:Type local:CollapsiblePanel}">
<ControlTemplate.Resources>
<sys:Boolean x:Key="BoolTrue">True</sys:Boolean>
<Style TargetType="FrameworkElement" x:Key="ExpandablePanelStyle">
<Setter Property="Width" Value="240"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsCollapsed,
RelativeSource={RelativeSource FindAncestor,
AncestorType=UserControl}}"
Value="{StaticResource BoolTrue}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="00:00:01" To="40"
Storyboard.TargetProperty="Width">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="00:00:01"
Storyboard.TargetProperty="Width">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</ControlTemplate.Resources>
<DockPanel LastChildFill="True" Style="{StaticResource ExpandablePanelStyle}">
<ToggleButton
Height="24" HorizontalAlignment="Left" DockPanel.Dock="Top"
IsChecked="{Binding IsCollapsed,
RelativeSource={RelativeSource FindAncestor,
AncestorType=UserControl}}">
Collapse
</ToggleButton>
<!-- здесь будет контент UserControl-а -->
<ContentPresenter/>
</DockPanel>
</ControlTemplate>
</UserControl.Template>
</UserControl>
В code-behind положите свойство IsCollapsed:
public partial class CollapsiblePanel : UserControl
{
public CollapsiblePanel()
{
InitializeComponent();
}
#region dp bool IsCollapsed
public bool IsCollapsed
{
get => (bool)GetValue(IsCollapsedProperty);
set => SetValue(IsCollapsedProperty, value);
}
public static readonly DependencyProperty IsCollapsedProperty =
DependencyProperty.Register("IsCollapsed", typeof(bool), typeof(CollapsiblePanel));
#endregion
}
Тестируем:
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:TestApp"
Title="Test" Width="500" Height="300">
<Grid>
<local:CollapsiblePanel HorizontalAlignment="Left">
<TextBlock Background="LightGray">Content</TextBlock>
</local:CollapsiblePanel>
</Grid>
</Window>
Получаем вот что:
