I have a list of items that is represented by separate view models. Each view model is listening to network event. I want to flash the background of a listview item when a specific error happen. I have tried using visual state groups with state triggers but it doesn't seem to work for me.
Here is what I have tried - MainWindow.xaml
:
<?xml version="1.0" encoding="utf-8"?><Window x:Class="FlashingTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:FlashingTest" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="FlashingTest"><ListView ItemsSource="{x:Bind ViewModel.Items}"><ListView.ItemTemplate><DataTemplate x:DataType="local:TestItemViewModel"><Border Margin="0,2,0,0" MinHeight="30" MinWidth="300"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="Flashing"><VisualState><VisualState.StateTriggers><StateTrigger IsActive="{Binding Flashing}" /></VisualState.StateTriggers><Storyboard><ColorAnimation Duration="0:0:0.3" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" To="GreenYellow" AutoReverse="True" /></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><TextBlock Text="{x:Bind Text}" /></Border></DataTemplate></ListView.ItemTemplate></ListView></Window>
MainWindow.xaml.cs
:
public sealed partial class MainWindow : Window{ public MainViewModel ViewModel { get; } = new(); public MainWindow() { this.InitializeComponent(); this.ViewModel.Items.Add(new() { Text = "First" }); this.ViewModel.Items.Add(new() { Text = "Second" }); this.ViewModel.Items.Add(new() { Text = "Third" }); }}
MainViewModel.cs
:
public class MainViewModel{ public ObservableCollection<TestItemViewModel> Items { get; } = new();}
TestItemViewModel.cs
(network event simulated with a timer)
public class TestItemViewModel : INotifyPropertyChanged{ private readonly DispatcherTimer _timer; private bool _flashing = false; public event PropertyChangedEventHandler PropertyChanged; public bool Flashing { get => _flashing; set => SetProperty(ref _flashing, value); } public TestItemViewModel() { _timer = new DispatcherTimer(); _timer.Interval = TimeSpan.FromMilliseconds(250); _timer.Tick += (s, e) => { if (Random.Shared.Next() % 3 == 0) Flashing = true; }; _timer.Start(); } public string Text { get; set; } protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { field = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }}