Как мне затемнить текст, изменить его и снова включить?

Я использую TextBlock в табличке данных для ячейки в сетке данных. У меня есть требование, согласно которому при изменении значения ячейки текст должен:

  • исчезать перед изменением
  • значение должно измениться
  • снова исчезнуть

На данный момент я использую TargetUpdated RoutedEvent для запуска анимации, чтобы текст исчез, а затем вернулся. Но исчезновение происходит после того, как текст уже изменил значение на экране.

<DataTemplate>
    <Border>
        <TextBlock Name="templateTextBlock" Text="{Binding Path=FirstName, NotifyOnTargetUpdated=True}" />
    </Border>
    <DataTemplate.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard AutoReverse="True">
                    <DoubleAnimation Storyboard.TargetName="templateTextBlock" Storyboard.TargetProperty="Opacity" To=".1" Duration="0:0:.5" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

У меня вопрос: как добиться желаемого эффекта - исчезнуть, изменить текст, исчезнуть?

Большое спасибо.


person Peanut    schedule 02.06.2011    source источник
comment
Глупые требования к победе.   -  person H.B.    schedule 03.06.2011


Ответы (1)


Написал интерактивное поведение, которое должно делать следующее:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<TextBlock Text="{Binding Name, NotifyOnTargetUpdated=True}">
    <i:Interaction.Behaviors>
        <b:AnimatedTextChangeBehavior AnimationDuration="0:0:0.1" />
    </i:Interaction.Behaviors>
</TextBlock>
class AnimatedTextChangeBehavior : Behavior<TextBlock>
{
    public Duration AnimationDuration { get; set; }

    private string OldValue = null;
    private string NewValue = null;

    DoubleAnimation AnimationOut;
    DoubleAnimation AnimationIn;

    protected override void OnAttached()
    {
        base.OnAttached();

        AnimationOut = new DoubleAnimation(1, 0, AnimationDuration, FillBehavior.HoldEnd);
        AnimationIn = new DoubleAnimation(0, 1, AnimationDuration, FillBehavior.HoldEnd);
        AnimationOut.Completed += (sOut, eOut) =>
        {
            AssociatedObject.SetCurrentValue(TextBlock.TextProperty, NewValue);
            OldValue = NewValue;
            AssociatedObject.BeginAnimation(TextBlock.OpacityProperty, AnimationIn);
        };

        Binding.AddTargetUpdatedHandler(AssociatedObject, new EventHandler<DataTransferEventArgs>(Updated));
    }

    private void Updated(object sender, DataTransferEventArgs e)
    {
        string value = AssociatedObject.GetValue(TextBlock.TextProperty) as string;
        AssociatedObject.BeginAnimation(TextBlock.OpacityProperty, AnimationOut);
        NewValue =  value;
        if (OldValue == null)
        {
            OldValue = value;
        }
        AssociatedObject.SetCurrentValue(TextBlock.TextProperty, OldValue);
    }
}

Если вы не хотите использовать Интерактивность Blend SDK для этого вы можете просто взять код и преобразовать его в отдельный класс и использовать событие Loaded TextBlock для настройки.

person H.B.    schedule 03.06.2011
comment
Я действительно рад, что нашел этот пост. Для этого я использовал 2 текстовых блока и анимацию. Это намного чище. - person german129; 31.10.2014
comment
@ H.B. Могу ли я узнать, на какое пространство имен ссылается ‹b:? - person abc cba; 16.03.2015
comment
@abccba: это ссылается на пространство имен класса, который я определяю в приведенном ниже фрагменте. Так что что-то вроде clr-namespace:YourProject.YourNamespace, зависит от того, куда вы его положили. - person H.B.; 16.03.2015
comment
Стоит отметить, что должен присутствовать NotifyOnSourceUpdated=True Text Binding, иначе это поведение не сработает (меня все равно поймали!). - person Andrew Stephens; 10.09.2015