2011-12-27 59 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讓它再次工作。