c# - Flash background of a listview item when an network event occurred - Stack Overflow

I have a list of items that is represented by separate view models. Each view model is listening to net

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=";
    xmlns:x=";
    xmlns:local="using:FlashingTest"
    xmlns:d=";
    xmlns:mc=";
    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));
    }
}

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/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft/winfx/2006/xaml"
    xmlns:local="using:FlashingTest"
    xmlns:d="http://schemas.microsoft/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats./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));
    }
}
Share Improve this question edited Mar 22 at 8:54 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Mar 22 at 7:36 yasaryasar 13.7k30 gold badges97 silver badges170 bronze badges 1
  • You have a "Border" and a "Border.Background" in your template; you do not have a "Panel" (e.g. Grid) in your template. – Gerry Schmitz Commented Mar 22 at 16:57
Add a comment  | 

1 Answer 1

Reset to default 0 +50

The following works on my end:

  • Name the Border.
  • Set the Border as target for the animation.
  • Use UserControl as a wrapper.
  • Change Panel to Border as suggested on the comments.
  • Set the Border's Background to Transparent. (Not sure why it doesn't work without this).
<ListView
    ItemsSource="{x:Bind ViewModel.Items}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:TestItemViewModel">
            <UserControl>
                <Border x:Name="RootBorder"
                    MinWidth="300"
                    MinHeight="30"
                    Margin="0,2,0,0">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup>
                            <VisualState>
                                <VisualState.StateTriggers>
                                    <StateTrigger IsActive="{x:Bind Flashing, Mode=OneWay}" />
                                </VisualState.StateTriggers>
                                <Storyboard>
                                    <ColorAnimation
                                        AutoReverse="True"
                                        Storyboard.TargetName="RootBorder"
                                        Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                        To="GreenYellow"
                                        Duration="0:0:0.3" />
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <TextBlock Text="{x:Bind Text}" />
                </Border>
            </UserControl>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Instead of wrapping it with a UserControl, creating a custom control should be a better idea to avoid performance issues.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744322661a4568496.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信