2009-06-08 4 views
1

Я спросил a question here, но потом понял, что проблема заключается не в коде, а в стиле, который я использую для кнопки. Поскольку проблема полностью отличается от той, которая была первоначально задана, я думал, что было бы более полезно для других пользователей, если бы я снова спросил «правильный» вопрос. Здесь я иду:WPF - No IsEnabled = истинное поведение с использованием стиля с анимацией

Я использую шаблон ниже в моей кнопке. Когда я устанавливаю button.IsEnabled = false, он работает нормально, но если я устанавливаю button.IsEnabled = true, он не включается. Не могли бы вы определить, что я делаю неправильно? Благодаря

<Style x:Key="BlackButtonStyle" TargetType="{x:Type Button}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type Button}"> 
       <ControlTemplate.Resources> 
        <Storyboard x:Key="MouseOverActivating"> 
         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> 
          <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2F2F2F"/> 
          <SplineColorKeyFrame KeyTime="00:00:00.1270000" Value="#FF2391FF"/> 
         </ColorAnimationUsingKeyFrames> 
        </Storyboard> 
        <Storyboard x:Key="MouseOverDeactivating"> 
         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="rectangle"> 
          <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2391FF"/> 
          <SplineColorKeyFrame KeyTime="00:00:00.2200000" Value="#FF2F2F2F"/> 

         </ColorAnimationUsingKeyFrames> 
        </Storyboard> 
        <Storyboard x:Key="PressActivating"> 
         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> 
          <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2391FF"/> 
          <SplineColorKeyFrame KeyTime="00:00:00.1370000" Value="#FF48D6FF"/> 
         </ColorAnimationUsingKeyFrames> 
        </Storyboard> 
        <Storyboard x:Key="PressedDeactivating" FillBehavior="Stop" > 
         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="rectangle"> 
          <SplineColorKeyFrame KeyTime="00:00:00" Value="#FF48D6FF"/> 
          <SplineColorKeyFrame KeyTime="00:00:00.2370000" Value="#FF2391FF"/> 
         </ColorAnimationUsingKeyFrames> 
        </Storyboard> 
        <Storyboard x:Key="DisableActivating"> 
         <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> 
          <SplineColorKeyFrame KeyTime="00:00:00" Value="#FFA7A7A7"/> 
         </ColorAnimationUsingKeyFrames> 
        </Storyboard> 
       </ControlTemplate.Resources> 
       <Grid> 
        <Rectangle Stroke="Transparent" RadiusX="5" RadiusY="5" x:Name="rectangle"> 
         <Rectangle.Fill> 
          <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
           <GradientStop Color="#FF000000" Offset="0"/> 
           <GradientStop Color="#FF2F2F2F" Offset="1"/> 
          </LinearGradientBrush> 
         </Rectangle.Fill> 
        </Rectangle> 
        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True" OpacityMask="{x:Null}"/> 
        <Rectangle Stroke="Transparent" RadiusX="5" RadiusY="5" x:Name="WhiteGlow"> 
         <Rectangle.Fill> 
          <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
           <GradientStop Color="#5BFFFFFF" Offset="0"/> 
           <GradientStop Color="#00FFFFFF" Offset="0.5"/> 
          </LinearGradientBrush> 
         </Rectangle.Fill> 
        </Rectangle> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsCancel" Value="False"/> 
        <EventTrigger RoutedEvent="FrameworkElement.Loaded"/> 
        <Trigger Property="IsFocused" Value="True"> 
         <Trigger.ExitActions> 
          <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard2"/> 
         </Trigger.ExitActions> 
         <Trigger.EnterActions> 
          <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard1"/> 
         </Trigger.EnterActions> 
        </Trigger> 
        <Trigger Property="IsDefaulted" Value="True"/> 
        <Trigger Property="IsMouseOver" Value="True"> 
         <Trigger.ExitActions> 
          <BeginStoryboard Storyboard="{StaticResource MouseOverDeactivating}" x:Name="MouseOverDeactivating_BeginStoryboard"/> 
         </Trigger.ExitActions> 
         <Trigger.EnterActions> 
          <BeginStoryboard Storyboard="{StaticResource MouseOverActivating}" x:Name="MouseOverActivating_BeginStoryboard"/> 
         </Trigger.EnterActions> 
        </Trigger> 
        <Trigger Property="IsPressed" Value="True"> 
         <Trigger.EnterActions> 
          <BeginStoryboard x:Name="PressActivating_BeginStoryboard" Storyboard="{StaticResource PressActivating}"/> 
         </Trigger.EnterActions> 
         <Trigger.ExitActions> 
          <BeginStoryboard x:Name="PressedDeactivating_BeginStoryboard" Storyboard="{StaticResource PressedDeactivating}"/> 
         </Trigger.ExitActions> 
        </Trigger> 
        <Trigger Property="IsEnabled" Value="False"> 
         <Trigger.EnterActions> 
          <BeginStoryboard Storyboard="{StaticResource DisableActivating}" x:Name="DisableActivating_BeginStoryboard"/> 
         </Trigger.EnterActions> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

ответ

0

Я подозреваю, что поведение, которое вы видите, является результатом анимации, который вы используете IsEnabled становится ложным. На DependencyProperties на самом деле есть приоритет, связанный с ними, в котором анимации высоко в списке; что иерархия, from MSDN, это: система

  • недвижимости принуждение
  • Активных анимации или анимации с поведением удержания.
  • Локальное значение
  • Свойства шаблона TemplatedParent
  • неявный стиль
  • Стиль запускает
  • шаблона вызывает
  • Стиль сеттеров
  • По умолчанию (тема) стиль
  • унаследованные от родительского
  • Значение по умолчанию от метаданных свойств зависимостей

По умолчанию у анимаций есть FillBehavior HoldEnd, что означает, что они остаются на значении, на котором закончилась анимация. Когда IsEnabled становится True через вашу привязку, это обновление происходит на уровне «Локальное значение» в приоритете, а так как раскадровка DisableActivating удерживает внешний вид на более высоком уровне приоритета («анимация с поведением Hold»), вы никогда не увидите кнопка изменится, как только она изменилась в первый раз.

Есть три решения этого:

  1. Обновления вашей анимации, чтобы иметь FillBehavior стоп-, что означает, что анимация не утверждает «IsEnabled = False» визуальный раз анимация останавливается. Вам понадобится стандартный неанимированный триггер с тем же состоянием, что и конец анимации, чтобы продолжать утверждать это после завершения анимации, поскольку в противном случае вы просто увидите, что он возвращается к состоянию, которое было, когда началась анимация , Поскольку это всего лишь триггерный набор, когда локальное значение обновляется, вы увидите, что оно возвращается к исходному значению, как вы ожидаете. Кроме того, поскольку анимация имеет более высокий приоритет, вы можете установить стиль и запустить анимацию одновременно и только «увидеть» эффекты стиля после завершения анимации (так что ваше затухание будет работать, как ожидалось).
  2. Вместо изменения FillBehavior вы можете создать новый триггер, который применяется, когда IsEnabled является True, который анимирует (возможно, мгновенно) обратно в исходное состояние. Это также можно сделать, применив анимацию в ExitAction триггера. Так как это также анимация, но была применена позже, она переопределит состояние HoldEnd другой анимации.В некотором смысле, это проще, чем вариант 1, но это может стать проблемой для поддержания прямой и обратной анимации, особенно если вам не нужна обратная анимация для конкретного визуального эффекта; однако вы можете сохранить его в и в отключенном состоянии.
  3. Добавьте ExitAction к своему триггеру IsEnabled, чтобы остановить раскадровку, не позволяя анимации продолжать утверждать значение, имевшееся в конце анимации, чтобы можно было применить стиль локального значения. Этот параметр имеет преимущества от необходимости повторять стиль (как в # 1), а также не изменять анимацию (как в # 2).

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

+0

Спасибо Николаю. Это сводило с ума. –

+1

есть третий вариант, который мне нравится еще лучше. В Trigger.ExitActions установлен \t \t \t \t \t \t \t \t \t и т.д .. для других. – rmoore

+0

Отредактировано для включения опции rmoore, которая, вероятно, является лучшим решением здесь. –

1

Самый простой вариант, чтобы добавить анимацию в триггер ExitAction IsEnabled, что возвратятся анимацию в EnterAction

+0

Спасибо, Нир. Ваш ответ в сочетании с Николасом помог мне исправить мою проблему. Что я сделал: 1) Создан новый раскадровки под названием DisableDeactivating и установите FillBehavior = «Стоп» (предложение Николая) 2) Затем, добавляемые в BeginStoryboard для DisableDeactivating в Trigger.ExitActions в IsEnabled = ложный триггер , Спасибо вам обоим !!! –