2011-12-27 87 views
0

我有一个WPF自定义控件我在一个名为Flasher的WPF控件库项目中定义。基本上,它的Fill属性在两种颜色之间来回闪烁,如控制台上的闪烁灯。这里是模板的控制,这是在Generic.xaml文件库:WPF关键帧动画工作,但现在不正确

<Style TargetType="{x:Type local:Flasher}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:Flasher}"> 
       <Grid Name="LayoutRoot"> 
        <Grid.Resources> 
         <Storyboard x:Key="FlashingStoryboard" AutoReverse="True" RepeatBehavior="Forever"> 
          <ColorAnimationUsingKeyFrames BeginTime="00:00:00" 
                  Storyboard.TargetName="Flasher" 
                  Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"> 
           <LinearColorKeyFrame KeyTime="00:00:00.5" 
                Value="{Binding Path=FlashColor, RelativeSource={RelativeSource AncestorType={x:Type local:Flasher}}}"/> 
          </ColorAnimationUsingKeyFrames> 
          <DoubleAnimation Duration="00:00:00.05" 
              From="0" To="10" 
              Storyboard.TargetName="FlasherBlur" 
              Storyboard.TargetProperty="Radius"> 
          </DoubleAnimation> 
         </Storyboard> 
        </Grid.Resources> 

        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="FlashStates"> 
          <VisualState x:Name="Flashing" Storyboard="{DynamicResource ResourceKey=FlashingStoryboard}"/> 
          <VisualState x:Name="Stopped"/> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 

        <Rectangle Fill="{TemplateBinding Fill}" 
           Name="Flasher" 
           Stroke="{TemplateBinding Stroke}" 
           StrokeThickness="{TemplateBinding StrokeThickness}"> 
         <Rectangle.Effect> 
          <BlurEffect x:Name="FlasherBlur" Radius="0" /> 
         </Rectangle.Effect> 
        </Rectangle> 

       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

这里的代码隐藏控制:

public partial class Flasher : Control { 

    public static readonly DependencyProperty FillProperty = 
     DependencyProperty.Register("Fill", typeof(Brush), typeof(Flasher), 
            new FrameworkPropertyMetadata (new SolidColorBrush(Colors.Silver), FrameworkPropertyMetadataOptions.AffectsRender)); 

    public static readonly DependencyProperty FlashColorProperty = 
     DependencyProperty.Register("FlashColor", typeof(Color), typeof(Flasher), 
            new FrameworkPropertyMetadata(Colors.Transparent, FrameworkPropertyMetadataOptions.AffectsRender)); 

    public static readonly DependencyProperty FlashDurationProperty = 
     DependencyProperty.Register("FlashDuration", typeof(TimeSpan), typeof(Flasher), new FrameworkPropertyMetadata(TimeSpan.MinValue)); 

    public static readonly DependencyProperty StrokeProperty = 
     DependencyProperty.Register("Stroke", typeof(Brush), typeof(Flasher), 
            new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Silver), FrameworkPropertyMetadataOptions.AffectsRender)); 

    public static readonly DependencyProperty StrokeThicknessProperty = 
     DependencyProperty.Register("StrokeThickness", typeof(double), typeof(Flasher), 
            new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender)); 

    protected Application App { 
     get { return Application.Current; } 
    } 

    protected ILog Log { 
     get { return (ILog) App.Properties[ "Log" ]; } 
    } 

    public Brush Fill { 
     get { return (Brush) GetValue(FillProperty); } 
     set { SetValue(FillProperty, value); } 
    } 

    public Color FlashColor { 
     get { return (Color) GetValue(FlashColorProperty); } 
     set { SetValue(FlashColorProperty, value); } 
    } 

    public TimeSpan FlashDuration { 
     get { return (TimeSpan) GetValue(FlashDurationProperty); } 
     set { SetValue(FlashDurationProperty, value); } 
    } 

    private bool flashing = false; 

    public bool IsFlashing { 
     get { return flashing; } 
     set { 
      flashing = value; 
      FrameworkElement grid = Template.FindName("LayoutRoot", this) as FrameworkElement; 
      if (flashing) { 
       if (!VisualStateManager.GoToElementState(grid, "Flashing", true)) { 
        Log.Debug("Flasher.cs: Visual State Manager transition failed."); 
       } 
       if (FlashDuration > TimeSpan.MinValue) { 
        ThreadPool.QueueUserWorkItem(WaitForDuration, FlashDuration); 
       } 
      } else { 
       if (!VisualStateManager.GoToElementState(grid, "Stopped", true)) { 
        Log.Debug("Flasher.cs: Visual State Manager transition failed."); 
       } 
      } 
     } 
    } 

    public Brush Stroke { 
     get { return (Brush) GetValue(StrokeProperty); } 
     set { SetValue(StrokeProperty, value); } 
    } 

    public double StrokeThickness { 
     get { return (double) GetValue(StrokeThicknessProperty); } 
     set { SetValue(StrokeThicknessProperty, value); } 
    } 

    public Flasher() : base() {} 

    static Flasher() { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(Flasher), new FrameworkPropertyMetadata(typeof(Flasher))); 
    } 

    private void TurnFlashingOff() { 
     // Set IsFlashing to false 
     IsFlashing = false; 
    } 

    private void WaitForDuration(object state) { 
     System.Threading.Thread.Sleep((TimeSpan) state); 

     Dispatcher.BeginInvoke(new Action(TurnFlashingOff)); 
    } 
} 

这是所有工作在几个月前,但现在不工作。也就是说,我曾经在使用控件的窗口中设置的两种颜色之间看到闪光灯改变颜色。我在IsFlashing setter中设置了断点,我知道FindName调用正在返回Grid,并且我知道VisualStateManager调用工作,所以我不明白为什么我没看到颜色改变。这令我颇为困惑。

加上Snoop似乎无法找到出现问题的窗口。这不是我应用程序的主窗口,而是无模式弹出窗口。从本质上讲,问题的窗口从Window下降,并使用以下代码创建并显示:

if (Window == null) { 
    Window = new MyDialog(); 
    // Set some program-specific window properties that don't affect the display here . . . 
    Window.Show(); 
} 

所以Snoop已经没用了。

如果在我发布的代码中没有明显的错误,那么我将不得不在我的代码的其他地方查找问题。

感谢您提供任何帮助。

托尼

回答

1

我已经找到了解决问题的办法通过XAML代码从时间与较早版本时,我知道这是工作。事实证明,在某些时候,我将Visual State Manager的Flashing状态中的StoryBoard标签更改为DynamicResource;当它工作时,我将它设置为StaticResource。将它改回到StaticResource让它再次工作。