WPF Keyframe анимация работала, но сейчас не работает - PullRequest
0 голосов
/ 27 декабря 2011

У меня есть пользовательский элемент управления WPF, определенный в проекте библиотеки элементов управления WPF, который называется Flasher.По сути, это прямоугольник, свойство Fill мигает между двумя цветами, как мигающий индикатор на консоли.Вот шаблон для элемента управления, который находится в файле Generic.xaml для библиотеки:

<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, и я знаю, что вызов FindName возвращает Grid, и я знаю, что вызовы VisualStateManager работают, поэтому я не понимаю, почему я не вижу изменения цветов.Это меня сильно озадачило.

Плюс, похоже, Snoop не может найти окно, в котором возникла проблема.Это не главное окно моего приложения, а немодальное всплывающее окно.По сути, окно с проблемой происходит из окна и создается и отображается со следующим кодом:

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

То есть Snoop был бесполезен.

Если в коде нет явных ошибокЯ опубликовал, а затем мне придется поискать проблему в другом месте моего кода.

Спасибо за любую помощь, которую вы можете оказать.

Тони

1 Ответ

1 голос
/ 31 декабря 2011

Я нашел решение проблемы, сравнив код xaml с более ранней версией, когда я знал, что она работает.Оказывается, в какой-то момент я изменил тег StoryBoard в состоянии мигания диспетчера визуальных состояний на DynamicResource;когда это сработало, я установил StaticResource.При возврате на StaticResource он снова заработал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...