Анимация между визуальными состояниями без взрыва определенных переходов - PullRequest
0 голосов
/ 02 марта 2011

У меня есть довольно простой сценарий, который я пытаюсь реализовать в Silverlight, но, несмотря на все невероятно мощные функции перехода в Silverlight / Blend 4, я просто не могу понять, как это сделать.

У меня есть макет, который сводится к следующему:

<UserControl>
    <Grid>
        <StackPanel>
            <Button x:Name="Button1" />
            <Button x:Name="Button2" />
            <Button x:Name="Button3" />
            <Button x:Name="Button4" />
        </StackPanel>
        <Grid x:Name="Page1" />
        <Grid x:Name="Page2" />
        <Grid x:Name="Page3" />
        <Grid x:Name="Page4" />
    </Grid>
</UserControl>

Сначала все четыре сетки страниц скрываются и масштабируются до нулевого размера, но когда вы нажимаете соответствующую кнопку, страница должна отображаться сРастущая анимация.При нажатии другой кнопки предыдущая страница должна исчезнуть с уменьшающейся анимацией, а другая страница должна отображаться с растущей анимацией.Таким образом, вы можете использовать кнопки для перехода между всеми четырьмя страницами.

«Правильный» способ сделать это, из того, что я прочитал, - это использовать визуальные состояния в пользовательском элементе управления.Таким образом, я создал четыре состояния, от Page1 до Page4, и для каждого состояния установил соответствующую сетку страницы для отображения.Затем я помещаю команды на кнопки, чтобы изменить визуальное состояние пользовательского элемента управления.Это работало нормально, и я мог переключаться между страницами, но когда я начал пытаться определить анимацию между состояниями, у меня возникли проблемы.

Сначала я подумал, что могу определить 'To *' и 'From* анимация для каждого государства.Поэтому, когда вы были в состоянии Page1 и нажимали кнопку, чтобы перейти в состояние Page2, она воспроизводила анимацию «От *», скрывающую страницу Page1, а затем анимацию «Кому *», отображающую страницу Page2.Но это не работает.Даже если вы определили анимацию «До *» и «От *» для каждого состояния, Silverlight воспроизводит только анимацию «До *» и полностью игнорирует анимацию «От *»!

Еще хуже, этоКажется, именно так и работает Silverlight, хотя в этом нет никакого смысла!Это означает, что если я хочу, чтобы каждая страница уменьшалась, а затем увеличивалась другая страница, мне нужно было бы определить отдельный переход от каждого состояния к другому состоянию!Для моих текущих четырех страниц это будет означать двенадцать отдельных переходов, но когда я хочу увеличить количество страниц, это число будет расти.Десять страниц потребуют 9 * 9 = 81 переходов!Все, чтобы уменьшить текущую страницу и увеличить новую.

Я не могу поверить, что нет лучшего способа справиться с таким простым сценарием, но я ничего не могунайти, кажется, сказать, как.Я мог бы, вероятно, взломать его вместе, используя codebehind, который изменяет раскадровки, но я хочу разрешить просмотр и редактирование сеток страниц в Blend, а также все, что я прочитал, чтобы избежать использования codebehind и использования моделей представления и визуальных состояний для обработки вещей

Пожалуйста, скажите мне, что я упускаю что-то очевидное?

1 Ответ

3 голосов
/ 03 марта 2011

В Blend вы просто нажимаете на состояние на вкладке «Состояния», чтобы начать запись состояния, определяете, как должно выглядеть состояние, и задаете продолжительность перехода состояния.

Вам не нужно беспокоиться о каждой отдельной перестановке переходов между состояниями, если только вы не хотите, чтобы каждый из них был разным.

Если в ваших состояниях используются свойства, которые нельзя «линейно» анимировать (как изменение видимости), проверьте кнопку FluidLayout.

Редактировать: Вы можете создать описанный вами эффект «полного сжатия и роста», используя только одну дополнительную раскадровку для каждого состояния - переход «Любое -> {Состояние}»,установка задержки BeginTime перед увеличением текущего элемента.

<UserControl
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:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="CommandingLeakWithScrollbar.UserControl1"
d:DesignWidth="640" d:DesignHeight="480">

<Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1"/>
                <VisualTransition GeneratedDuration="0:0:1" To="Page1">
                    <Storyboard>
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True"/>
                    </Storyboard>
                </VisualTransition>
                <VisualTransition GeneratedDuration="0:0:1" To="Page2">
                    <Storyboard>
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True" />
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                    </Storyboard>
                </VisualTransition>
                <VisualTransition From="None" GeneratedDuration="0:0:1" To="Page1"/>
                <VisualTransition From="None" GeneratedDuration="0:0:1" To="Page2"/>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="None"/>
            <VisualState x:Name="Page1">
                <Storyboard>
                    <DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                    <DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Page2">
                <Storyboard>
                    <DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                    <DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid x:Name="grid1"  Background="Beige" Width="40" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <Grid x:Name="grid2" HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Top" Background="Wheat" />
    <Grid HorizontalAlignment="Left" Width="40" Height="40" VerticalAlignment="Bottom" />
    <Grid HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Bottom"/>
    <StackPanel HorizontalAlignment="Center">
        <Button Content="Reset" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="None"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Page1" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="Page1"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Page2" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="Page2"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </StackPanel>
</Grid>

...