2011-01-28 3 views
8

Как раз тогда, когда я думаю, что понимаю VisualStateManager, что-то доказывает, что я неправ.VisualStateManager и сгенерированные переходы

Я использую WPF 4 и пытаюсь просто увеличить элемент на мыши и сжать его обратно на мышь. Я полагал, что я просто определить каждое состояние в VisualStateGroup, а затем указать VisualTransition с GeneratedDuration:

<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5"> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup Name="CommonStates"> 
      <VisualStateGroup.Transitions> 
       <VisualTransition GeneratedDuration="0:0:1"/> 
      </VisualStateGroup.Transitions> 

      <VisualState Name="Normal"/> 

      <VisualState Name="MouseOver"> 
       <Storyboard> 
        <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" Duration="0"/> 
        <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1.5" Duration="0"/> 
       </Storyboard> 
      </VisualState> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 

    <Border.RenderTransform> 
     <ScaleTransform x:Name="scaleTransform" ScaleX="1" ScaleY="1"/> 
    </Border.RenderTransform> 

    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
</Border> 

Поскольку у меня есть всеобъемлющая VisualTransition с GeneratedDuration, я ожидал, что VSM для создания промежуточных анимации. То есть, мышка над контрольным элементом должна анимировать свойства ScaleTransform от 1 до 1,5 в течение 1 секунды. То же самое с мытьем. Вместо этого есть задержка на 1 секунду, а затем ScaleTransform свойства мгновенно привязывается к 1,5 или назад к 1.

Если я вручную указать переходы следующим образом, то я получаю желаемое поведение:

<VisualStateGroup.Transitions> 
    <VisualTransition From="Normal" To="MouseOver"> 
     <Storyboard> 
      <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" Duration="{StaticResource MouseEnterDuration}"/> 
      <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1.5" Duration="{StaticResource MouseEnterDuration}"/> 
     </Storyboard> 
    </VisualTransition> 

    <VisualTransition From="MouseOver" To="Normal"> 
     <Storyboard> 
      <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1" Duration="{StaticResource MouseLeaveDuration}"/> 
      <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1" Duration="{StaticResource MouseLeaveDuration}"/> 
     </Storyboard> 
    </VisualTransition> 
</VisualStateGroup.Transitions> 

Но почему Я должен это сделать? Я думал, что вся суть сгенерированных переходов состояла в том, что переход, как вы знаете, будет сгенерирован. Что я не понимаю здесь?

UPDATE: В соответствии с ответом Стога, смесь создает что-то, что делает работу. Таким образом, работая назад, я решил, что это действительно факт, что я ссылаюсь только на ScaleTransform, а не через UIElement, который содержит его. Я изменил мой XAML к следующему и он работает, как ожидалось:

<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5"> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup Name="CommonStates"> 
      <VisualStateGroup.Transitions> 
       <VisualTransition From="Normal" To="MouseOver" GeneratedDuration="{StaticResource MouseEnterDuration}"/> 

       <VisualTransition From="MouseOver" To="Normal" GeneratedDuration="{StaticResource MouseLeaveDuration}"/> 
      </VisualStateGroup.Transitions> 

      <VisualState Name="Normal"/> 

      <VisualState Name="MouseOver"> 
       <Storyboard> 
        <DoubleAnimation Storyboard.TargetName="PART_Root" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)" To="{StaticResource MouseOverScale}" Duration="0"/> 
        <DoubleAnimation Storyboard.TargetName="PART_Root" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" To="{StaticResource MouseOverScale}" Duration="0"/> 
       </Storyboard> 
      </VisualState> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 

    <Border.RenderTransform> 
     <ScaleTransform/> 
    </Border.RenderTransform> 

    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
</Border> 

Кажется смешным (и очевидная ошибка), но она работает.

Благодаря

+0

Эта ошибка также может быть вызвана переутомлением синтаксиса каста. Например, '(Border.Background). (Brush.Opacity)' не работает, но 'Background.Opacity' отлично работает. – Artfunkel

ответ

6

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

<Grid> 
    <Grid.Resources> 
     <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
         <Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5"> 
          <Border.RenderTransform> 
           <TransformGroup> 
            <ScaleTransform/> 
            <SkewTransform/> 
            <RotateTransform/> 
            <TranslateTransform/> 
           </TransformGroup> 
          </Border.RenderTransform> 
          <VisualStateManager.VisualStateGroups> 
           <VisualStateGroup Name="CommonStates"> 
            <VisualStateGroup.Transitions> 
             <VisualTransition GeneratedDuration="0:0:1"/> 
            </VisualStateGroup.Transitions> 
            <VisualState Name="Normal"/> 
            <VisualState x:Name="MouseOver"> 
             <Storyboard> 
              <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="PART_Root"> 
               <EasingDoubleKeyFrame KeyTime="0" Value="2"/> 
              </DoubleAnimationUsingKeyFrames> 
              <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="PART_Root"> 
               <EasingDoubleKeyFrame KeyTime="0" Value="2"/> 
              </DoubleAnimationUsingKeyFrames> 
             </Storyboard> 
            </VisualState> 
           </VisualStateGroup> 
          </VisualStateManager.VisualStateGroups> 
          <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Grid.Resources> 
    <Button Content="Button" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Style="{StaticResource ButtonStyle1}"/> 
</Grid> 

Хотя смесь использует более общую группу преобразования, главное отличие мы можем видеть, что цели раскадровки элемент и путь собственности через который элемент к коэффициентам масштабирования.

+1

Спасибо Рик. Я обновил свой вопрос, чтобы включить конечное решение. – cantloginfromwork