How to initiate a textblock text animation on a condition?

don bradman 621 Reputation points
2023-06-08T07:02:41.57+00:00

I have a WPF app, where there is a textblock like below:

<TextBlock
	Name="pendingBillsLabel"
	FontFamily="Segoe UI Historic"
	FontSize="20">
	<Run Text="Upcoming Bills to be Processed : " Foreground="#29B6F6"/>
	<Run Text="{Binding PendingBills.Count, Mode=OneWay}"

Currently I have added a blinking animation to it as below:

	<TextBlock.Style>
		<Style TargetType="{x:Type TextBlock}">
			<Style.Triggers>
				<Trigger Property="Visibility" Value="Visible">
					<Trigger.EnterActions>
						<BeginStoryboard>
							<Storyboard>
								<DoubleAnimation Storyboard.TargetProperty="Opacity"
								                 From="1.5" To="0.0" Duration="0:0:0.8"
								                 AutoReverse="True" RepeatBehavior="Forever"/>
							</Storyboard>
						</BeginStoryboard>
					</Trigger.EnterActions>
				</Trigger>
			</Style.Triggers>
		</Style>
	</TextBlock.Style>

But this animation runs all the time.

I want this animation to run only when PendingBills.Count is 0 where PendingBills is a property of type ICollectionView declared in my VM.

How can I do this?

Developer technologies | Windows Presentation Foundation
Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,681 Reputation points Microsoft External Staff
    2023-06-08T08:43:11.2833333+00:00

    Hi,@don bradman. You could refer to the following codes according to your needs.
    It is recommended that you set RepeatBehavior to 3 times. If it is Forever, it will still flash when the Count is not 0.

    <Window.Resources>
            <CollectionViewSource x:Key="PendingBills" Source="{Binding Users}" />
       
        </Window.Resources>
        <Window.DataContext>
            <local:ViewModel/>
        </Window.DataContext>
        <StackPanel>
    
    
            <DataGrid ItemsSource="{Binding Source={StaticResource PendingBills}}"  Height="180">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="name" Binding="{Binding Name}"/>
                </DataGrid.Columns>
            </DataGrid>
            <TextBox Text="{Binding FilterText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="200"/>
    
            <TextBlock	Name="pendingBillsLabel"	FontFamily="Segoe UI Historic"	FontSize="20"
                       >
    	      <Run Text="Upcoming Bills to be Processed : " Foreground="#29B6F6" />
    	      <Run Text="{Binding PendingBills.Count, Mode=OneWay}"/>
    
                <TextBlock.Style>
                    <Style TargetType="{x:Type TextBlock}">
                  
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding PendingBills.Count}" Value="0">
                                <DataTrigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                                 From="1.5" To="0.0" Duration="0:0:0.8"
                                                 AutoReverse="True" RepeatBehavior="Forever" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.EnterActions>
                            </DataTrigger>
                            
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
    
            </TextBlock>
          
        </StackPanel>
    

    Codebedhind:

       public class ViewModel : INotifyPropertyChanged
        {
           
            private ICollectionView icv;
    
            public ICollectionView PendingBills
            {
                get { return icv; }
                set
                {
                    icv = value;
                    OnPropertyChanged("PendingBills ");
                }
            }
            private ObservableCollection<User> users = new ObservableCollection<User>();
            public ObservableCollection<User> Users
            {
                get { return users; }
                set
                {
                    if (users != value)
                    {
                        users = value;
                        OnPropertyChanged("Users");
                    }
                }
            }
            public ICommand ApplyFilterCommand { get; set; }
            public ViewModel()
            {
                Users.Add(new User() { Id = 1, Name = "user1" });
                Users.Add(new User() { Id = 2, Name = "user2" });
                Users.Add(new User() { Id = 3, Name = "user3" });
                Users.Add(new User() { Id = 5, Name = "user4" });
                Users.Add(new User() { Id = 6, Name = "user5" });
                PendingBills = CollectionViewSource.GetDefaultView(Users);
    
            }
            private string _filterText;
            public string FilterText
            {
                get { return _filterText; }
                set
                {
                    _filterText = value;
                    ApplyFilter();
                    OnPropertyChanged(nameof(FilterText));
                }
            }
       
            public void ApplyFilter()
            {
                if (string.IsNullOrEmpty(FilterText))
                {
                    PendingBills.Filter = null;
                }
                else
                {
                    PendingBills.Filter = item => ((User)item).Name.Contains(FilterText);
                }
             
            }
            
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged([CallerMemberName] string name = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
        }
    
        public class User
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        public class RelayCommand : ICommand
        {
            private Action<object> execute;
            private Func<object, bool> canExecute;
    
            public RelayCommand(Action<object> executeAction, Func<object, bool> canExecuteFunc = null)
            {
                execute = executeAction ?? throw new ArgumentNullException(nameof(executeAction));
                canExecute = canExecuteFunc;
            }
    
            public event EventHandler CanExecuteChanged
            {
                add => CommandManager.RequerySuggested += value;
                remove => CommandManager.RequerySuggested -= value;
            }
    
            public bool CanExecute(object parameter)
            {
                return canExecute == null || canExecute(parameter);
            }
    
            public void Execute(object parameter)
            {
                execute(parameter);
            }
        }
    

    The result:

    7

    Update:

    <Window.Resources>
            <CollectionViewSource x:Key="PendingBills" Source="{Binding Users}" />
           
        </Window.Resources>
        <Window.DataContext>
            <local:ViewModel/>
        </Window.DataContext>
        <StackPanel>
    
    
            <DataGrid ItemsSource="{Binding Source={StaticResource PendingBills}}"  Height="180">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="name" Binding="{Binding Name}"/>
                </DataGrid.Columns>
            </DataGrid>
            <TextBox Text="{Binding FilterText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="200"/>
    
            <TextBlock	Name="pendingBillsLabel"	FontFamily="Segoe UI Historic"	FontSize="20"
                       >
    	      <Run Text="Upcoming Bills to be Processed : " Foreground="#29B6F6" />
    	      <Run Text="{Binding PendingBills.Count, Mode=OneWay}"/>
    
                <TextBlock.Style>
                    <Style TargetType="{x:Type TextBlock}">
                  
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding PendingBills.Count}" Value="0">
                                <DataTrigger.EnterActions>
                                    <BeginStoryboard  x:Name="AnimationStoryboard">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                         From="1.5" To="0.0" Duration="0:0:0.8"
                                         AutoReverse="True" RepeatBehavior="Forever" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.EnterActions>
                                <DataTrigger.ExitActions>
                                    <RemoveStoryboard BeginStoryboardName="AnimationStoryboard" />
                                </DataTrigger.ExitActions>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
    
            </TextBlock>
          
        </StackPanel>
    

    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.