You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF MVVM中实现图片多次闪烁?闪烁次数需在ViewModel指定且支持运行时修改

Alright, let's build this dynamic image blinking feature in WPF using MVVM—where the number of blinks is controlled by the ViewModel and can be adjusted on the fly while the app's running. I'll break this down into clear, actionable parts that follow MVVM principles.

Step 1: Create a Reusable ViewModel Base Class

First, let's start with a base ViewModel that implements INotifyPropertyChanged—this is the backbone of MVVM for keeping the View in sync with ViewModel changes:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}
Step 2: Implement the Main ViewModel

Next, the MainViewModel will handle all the blink logic, hold the configurable blink count, and manage the image's visibility state. We'll use DispatcherTimer to safely update UI elements since we're working with WPF's UI thread:

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

public class MainViewModel : ViewModelBase
{
    private int _blinkCount;
    private bool _isImageVisible = true;
    private int _currentBlinkCycle;
    private readonly DispatcherTimer _blinkTimer;
    private ICommand? _startBlinkCommand;

    public MainViewModel()
    {
        _blinkTimer = new DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(500) // Adjust blink speed here (500ms = 0.5s per toggle)
        };
        _blinkTimer.Tick += BlinkTimer_Tick;
    }

    public int BlinkCount
    {
        get => _blinkCount;
        set => SetField(ref _blinkCount, value);
    }

    public bool IsImageVisible
    {
        get => _isImageVisible;
        set => SetField(ref _isImageVisible, value);
    }

    public ICommand StartBlinkCommand => _startBlinkCommand ??= new RelayCommand(StartBlinking);

    private void BlinkTimer_Tick(object? sender, EventArgs e)
    {
        // Toggle image visibility
        IsImageVisible = !IsImageVisible;

        // Count a full blink cycle (visible → hidden → visible)
        if (!IsImageVisible)
        {
            _currentBlinkCycle++;
        }
        // Stop once we've hit the requested number of blinks
        else if (_currentBlinkCycle >= BlinkCount)
        {
            _blinkTimer.Stop();
            _currentBlinkCycle = 0;
        }
    }

    private void StartBlinking()
    {
        // Reset state before starting a new blink sequence
        _currentBlinkCycle = 0;
        IsImageVisible = true;
        _blinkTimer.Start();
    }

    // Simple RelayCommand implementation (replace with CommunityToolkit/Prism commands if you use those libraries)
    private class RelayCommand : ICommand
    {
        private readonly Action _execute;
        public event EventHandler? CanExecuteChanged;

        public RelayCommand(Action execute)
        {
            _execute = execute;
        }

        public bool CanExecute(object? parameter) => true;
        public void Execute(object? parameter) => _execute();
    }
}
Step 3: Build the View (XAML)

Now the View will bind to the ViewModel's properties. We'll use a BooleanToVisibilityConverter to map the IsImageVisible boolean to the image's Visibility state, plus controls to adjust the blink count and trigger the blinking:

<Window x:Class="WpfImageBlinker.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfImageBlinker"
        Title="Dynamic Image Blinker" Height="450" Width="800">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConverter"/>
    </Window.Resources>
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="25">
        <!-- Blinking Image -->
        <Image Source="your-image-path.png" 
               Visibility="{Binding IsImageVisible, Converter={StaticResource BoolToVisConverter}}"
               Width="220" Height="220"/>
        
        <!-- Dynamic Blink Count Control -->
        <StackPanel Orientation="Horizontal" Spacing="12">
            <TextBlock Text="Blink Count:" VerticalAlignment="Center" FontSize="14"/>
            <TextBox Width="60" Text="{Binding BlinkCount, UpdateSourceTrigger=PropertyChanged}" FontSize="14"/>
        </StackPanel>
        
        <!-- Trigger Blinking -->
        <Button Content="Start Blinking" Command="{Binding StartBlinkCommand}" 
                Padding="12 6" FontSize="14"/>
    </StackPanel>
</Window>
Key Adjustments & Notes
  • Blink Definition: I defined a "blink" as a full visible→hidden→visible cycle. If you want a single toggle (visible→hidden) to count as one blink, move the _currentBlinkCycle++ line to run every tick instead of only when hiding the image.
  • Dynamic Count Updates: You can edit the blink count textbox even while blinking is in progress—the timer will automatically use the updated value on the next cycle.
  • Blink Speed: Adjust the DispatcherTimer.Interval value to make blinks faster (e.g., 300ms) or slower (e.g., 1000ms).
  • Image Source: Replace your-image-path.png with your actual image path (local resource, embedded resource, or URI).

内容的提问来源于stack exchange,提问作者Chad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:54:34