Пытаюсь сделать 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 шт):

Автор решения: VladD

Вы как-то делаете слишком сложно с анимацией. Вам нужно просто указать 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>

Получаем вот что:

гамбургер делаете, да?

→ Ссылка