Мигание текста в TextBlock
Как сделать так, чтобы при изменении текста в TextBlock'e текст замигал, но при возврате к TargetNullValue анимация не срабатывала бы.
XAML:
<TextBlock Text="{Binding IdRemoteStdWinner, NotifyOnTargetUpdated=True, TargetNullValue='Победитель не найден!'}"
FontSize="40"
Margin="2"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard Duration="0:0:5">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
FillBehavior="HoldEnd"
AutoReverse="True">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Black"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.1" Value="White"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.2" Value="Black"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.3" Value="White"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.4" Value="Black"/>
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Ответы (2 шт):
Решение так себе, но работает:
XAML:
<Viewbox Stretch="Uniform" StretchDirection="DownOnly">
<TextBlock Text="{Binding IdRemoteStdWinner, TargetNullValue='Игра запущена. Ждём ответов!'}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontSize" Value="40"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsAnimation}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames FillBehavior="Stop" RepeatBehavior="0:0:3"> Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Black"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.1" Value="White"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.2" Value="Black"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.3" Value="White"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.4" Value="Black"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="White"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.6" Value="Black"/>
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsAnimationEndGame}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.5"
To="Transparent"
FillBehavior="Stop"
RepeatBehavior="0:0:3"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Viewbox>
На вашем месте я бы сделал нечто такое:
<Style x:Key="TextBlock.TextBlink" TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="{Binding Text}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text}" Value="{x:Null}">
<Setter Property="Text" Value="Некий текст"/>
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="BlinkAnimation"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Name="BlinkAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" RepeatBehavior="Forever" AutoReverse="True" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
Как я говорил ранее в комментариях, вам надо при помощи DataTrigger проверять, равно-ли свойство NULL, если да, то анимация не требуется и мы ее можем вырубить. Делает в WPF это RemoveStoryboard (можно и с PauseStoryboard поиграться). Как видите, у DataTrigger есть EnterActions и ExitActions, тут думаю все понятно (в одном запускаем анимацию, в другом ее вырубаем).
Минус тут думаю очевиден, мы привязку делаем в стиле, что не есть хорошо. Увы, TextBlock не имеет ContentTemplate при помощи которого мы могли бы сделать {TemplateBinding Text}. Обходным решением будет стилизовать другой компонент, например TextBox, а лучше вовсе сделать свой контрол, где будет DependencyProperty с текстом.
Для проверки я лично набросаю такой интерфейс:
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Style="{StaticResource TextBlock.TextBlink}" TextAlignment="Center" FontSize="16"/>
<TextBox BorderThickness="0 0 0 1" Width="150" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
Ну и собственно сам результат:
А да, если у вас использование как у меня, то убедитесь, что привязанное свойство именно NULL, а не пустое, ибо когда вы удаляете все из TextBox (как у меня), то оно будет Text = "", не NULL. Решается простой проверкой, на подобие:
if (string.IsNullOrEmpty(value)) value = null;
в Set свойства. Если у вас используется лишь код, то пишите просто Text = null;, и этого достаточно.
