Как мне убрать текст, изменить его и снова ввести?

#wpf #animation #fade #textblock

#wpf #Анимация #исчезать #textblock

Вопрос:

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

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

На данный момент я использую 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>
  

Мой вопрос в том, как мне добиться требуемого эффекта — убрать, изменить текст, ввести?

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

Комментарии:

1. Глупые требования к win.

Ответ №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 для выполнения настройки.

Комментарии:

1. Я действительно рад, что нашел этот пост. Для этого я использовал 2 текстовых блока и анимацию. Это намного чище.

2. @H.B. Могу я узнать, какая ссылка на пространство имен для <b: ?

3. @abccba: это ссылается на пространство имен класса, которое я определяю во фрагменте ниже. Итак, что-то вроде clr-namespace:YourProject.YourNamespace , зависит от того, куда вы его поместили.

4. стоит отметить, что NotifyOnSourceUpdated=True должна присутствовать текстовая привязка, иначе такое поведение не сработает (в любом случае, это меня зацепило!).