WPF/XAML — Анимация содержимого расширителя

#wpf #xaml #animation #storyboard #expander

Вопрос:

Я пытаюсь добавить анимацию расширителя с помощью xaml (аналогичную той, которая используется в Windows 10), где при нажатии она выводит новую информацию из-под панели расширителя (прокручивается снизу вверх). Пример того, чего я пытаюсь достичь, можно найти в Windows 10, перейдя на панель управления, Параметры питания и щелкнув расширитель рядом с «Показать дополнительные планы».

У меня есть анимация для работы, но если я установлю свойство окна SizeToContent=»Высота» (которое я в конечном итоге хочу использовать, чтобы размер окна автоматически подстраивался под его содержимое), вместо этого расширенная информация прокручивается сверху вниз! Если я вручную отрегулирую высоту окна с помощью ручки (даже всего на 1 пиксель), а затем снова нажму на расширитель, анимация будет работать так, как я хочу (снизу вверх), но затем развернутая информация прокручивается выше верхней части окна >_>

Есть какие-нибудь идеи?

xaml:

 <Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Width="480"
        SizeToContent="Height">

    <StackPanel VerticalAlignment="Bottom">

        <!-- --><TextBlock Margin="5 0 0 0" Height="21">TITLE</TextBlock>

        <!-- First Panel -->
        <StackPanel>

            <!-- First Panel Style -->
            <StackPanel.Resources>
                <BooleanToVisibilityConverter x:Key="boolToVisibility" />
                <Style TargetType="StackPanel" x:Key="StackPanelMain">
                    <Style.Triggers>
                        <EventTrigger RoutedEvent="Expander.Expanded">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.25" To="160" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="Expander.Collapsed">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Style.Triggers>
                </Style>
                <Style TargetType="TextBox">
                    <Setter Property="Margin" Value="5 5 0 0" />
                    <Setter Property="Width" Value="360" />
                </Style>
            </StackPanel.Resources>

            <!-- First Panel Code -->
            <StackPanel Style="{StaticResource StackPanelMain}" Height="21">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Margin="5 0 0 0">First Panel</TextBlock>
                    <Separator Margin="5 0 5 0" Opacity="0.5" Width="360"/>
                    <Expander x:Name="FirstPanelExpander" />
                </StackPanel>
                <StackPanel Orientation="Vertical" Visibility="{Binding IsExpanded, ElementName=FirstPanelExpander, Converter={StaticResource boolToVisibility}}">
                    <TextBox />
                    <TextBox />
                    <TextBox />
                    <TextBox />
                    <TextBox />
                </StackPanel>
            </StackPanel>

        </StackPanel>

        <!-- Next Panel -->
        <StackPanel Height="21">

            <!-- Next Panel Code -->
            <TextBlock Margin="5 0 0 0">Next Panel</TextBlock>

        </StackPanel>

    </StackPanel>

</Window>

 

Ответ №1:

Прежде всего, нет необходимости скрывать свое Textboxes . Когда ваши объекты находятся внутри Expander , они уже будут скрыты, если expander они закрыты. Ниже приведен пример дизайна, близкого к тому, что вы хотите.

     <Window.Resources>
    <Style TargetType="Expander" x:Key="ExpanderMain">
        <Style.Triggers>
            <EventTrigger RoutedEvent="Expander.Expanded">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard >
                            <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.25" From="30" To="160" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
            <EventTrigger RoutedEvent="Expander.Collapsed">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard >
                            <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.25" From="160" To="30" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Style.Triggers>
    </Style>
    <Style TargetType="TextBox">
        <Setter Property="Margin" Value="5 5 0 0" />
        <Setter Property="Width" Value="360" />
    </Style>
</Window.Resources>

<ScrollViewer>
    <StackPanel>
        <Expander Name="AnimatedExpander" Style="{StaticResource ExpanderMain}">
            <Expander.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Panel - 1" />
                    <Separator Width="300" Margin="5,0,0,0"/>
                </StackPanel>
            </Expander.Header>
            <StackPanel>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
            </StackPanel>
        </Expander>

        <Expander Name="AnimatedExpander2" Style="{StaticResource ExpanderMain}">
            <Expander.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Panel - 2" />
                    <Separator Width="300" Margin="5,0,0,0"/>
                </StackPanel>
            </Expander.Header>
            <StackPanel>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
            </StackPanel>
        </Expander>

        <Expander Name="AnimatedExpander3" Style="{StaticResource ExpanderMain}">
            <Expander.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Panel - 3" />
                    <Separator Width="300" Margin="5,0,0,0"/>
                </StackPanel>
            </Expander.Header>
            <StackPanel>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
            </StackPanel>
        </Expander>

        <Expander Name="AnimatedExpander4" Style="{StaticResource ExpanderMain}">
            <Expander.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Panel - 4" />
                    <Separator Width="300" Margin="5,0,0,0"/>
                </StackPanel>
            </Expander.Header>
            <StackPanel>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
                <TextBox/>
            </StackPanel>
        </Expander>
    </StackPanel>

</ScrollViewer>
 

Комментарии:

1. спасибо за советы, но функционально ваш код делает то же самое, что и мой. поле по-прежнему загружается сверху вниз при нажатии на расширитель, и если размер окна изменяется вручную, то возникает та же проблема, что и у меня (когда поля загружаются снизу вверх, но загружаются за пределами окна и делают расширитель и первые несколько верхних полей недоступными) 😮

2. Извините, я неправильно понял. Я исправил это выше для вас. Когда он заключает свои расширители в ScrollViewer, область ScrollViewer будет открываться и закрываться в соответствии с содержимым страницы.

3. Что он делает то же самое? Вы буквально скопировали весь код?

4. Я предполагаю, что вы берете один из расширителей и устанавливаете его на VerticalAlignment="Bottom" . В этом случае делается отверстие вверх. Я не думаю, что вы привели VerticalAlignment="Bottom" пример дизайна на странице, о которой говорите. Есть расширители, выстроенные один за другим.

5. Потянув экран прокрутки вниз, когда расширители будут открыты, вы получите тот же пример дизайна. Вот как это выглядит в представлении, когда средство просмотра прокрутки опускается после открытия расширителя.