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

如何在XAML中实现GIF无限循环播放?

问题描述

在XAML和PowerShell开发中,使用MediaElement播放GIF时遇到循环故障:GIF仅播放一次就停滞。尝试过停止后设置Position = [TimeSpan]::Zero再播放、直接重新设置源等方法均无效;仅将源设为$null再重新赋值能实现循环,但会产生严重闪烁。

当前代码如下:

PowerShell代码

function Get-Controls
{
    # Find and assign various UI controls from the loaded XAML window by their names

    $global:Load_Installing_lbl = $global:window.FindName("Installing_lbl")
    $global:Load_Loader_gpl = $global:window.FindName("Loader_gpl")

    $global:LoaderNum = 1
    $Load_Loader_gpl.Source = [Uri]::new("$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif")

    $global:Load_Loader_gpl.Add_MouseLeftButtonDown({
        $global:LoaderNum++
        if (-not (Test-Path "$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif"))
        {
            $global:LoaderNum = 1
        }

        # Reset the loader to ensure the new GIF will play infinitely
        $Load_Loader_gpl.Stop()
        $Load_Loader_gpl.Source = [Uri]::new("$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif")
        $Load_Loader_gpl.Play()
    })

    $Load_Loader_gpl.add_MediaEnded({
        $wert = [Environment]::GetEnvironmentVariable("Installation", "User")
        if ($wert -eq "FINISH")
        {
            [Environment]::SetEnvironmentVariable("Installation", $null, "User")
            $global:Window.Close()
        }
        else
        {
            # Temporarily set the source to null to reset the GIF
            $Load_Loader_gpl.Stop()
            $Load_Loader_gpl.Position = [TimeSpan]::Zero # Set the initial position to zero
            Write-Host "t0.20"
            $Load_Loader_gpl.Play()
        }
    })

    # Ensure the GIF plays in an endless loop initially
    $Load_Loader_gpl.Position = [TimeSpan]::Zero # Set the initial position to zero
    $Load_Loader_gpl.Play()
}

XAML代码

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow" Height="300" Width="300" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Border CornerRadius="0, 20, 0, 20" Background="LightGray" BorderBrush="#FFFDC400" BorderThickness="5">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Name="Installing_lbl" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="24">Installing Test....</Label>
            <MediaElement Width="200" Height="200" Grid.Row="1" Margin="10" Name="Loader_gpl" LoadedBehavior="Manual" UnloadedBehavior="Stop">
            </MediaElement>
        </Grid>
    </Border>
</Window>
解决方案:用Image控件替代MediaElement实现无闪烁循环

MediaElement本身对GIF的循环播放支持有限,容易出现重置失效或闪烁问题。改用Image控件配合BitmapImage的动画特性,能更稳定地实现无闪烁无限循环。

修改后的XAML代码

将原有的MediaElement替换为Image控件:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow" Height="300" Width="300" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Border CornerRadius="0, 20, 0, 20" Background="LightGray" BorderBrush="#FFFDC400" BorderThickness="5">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Name="Installing_lbl" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="24">Installing Test....</Label>
            <!-- 替换MediaElement为Image控件 -->
            <Image Width="200" Height="200" Grid.Row="1" Margin="10" Name="Loader_img" Stretch="Uniform">
            </Image>
        </Grid>
    </Border>
</Window>

修改后的PowerShell代码

通过BitmapImage加载GIF,并利用其内置的动画循环特性,无需手动处理MediaEnded事件:

function Get-Controls
{
    $global:Load_Installing_lbl = $global:window.FindName("Installing_lbl")
    $global:Load_Loader_img = $global:window.FindName("Loader_img")

    $global:LoaderNum = 1

    # 定义加载GIF的函数
    function Load-Gif {
        param([string]$Path)
        $bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
        $bitmap.BeginInit()
        $bitmap.UriSource = [Uri]::new($Path)
        $bitmap.CacheOption = [System.Windows.Media.Imaging.BitmapCacheOption]::OnLoad
        $bitmap.EndInit()
        # 确保GIF动画循环播放
        $bitmap.DecodePixelWidth = 200 # 匹配Image控件宽度,避免拉伸失真
        $Load_Loader_img.Source = $bitmap
    }

    # 初始加载GIF
    Load-Gif -Path "$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif"

    # 点击切换GIF
    $global:Load_Loader_img.Add_MouseLeftButtonDown({
        $global:LoaderNum++
        $gifPath = "$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif"
        if (-not (Test-Path $gifPath))
        {
            $global:LoaderNum = 1
            $gifPath = "$PSScriptRoot\Loaders\Loader ($global:LoaderNum).gif"
        }
        Load-Gif -Path $gifPath
    })

    # 监听安装完成信号
    $timer = New-Object System.Windows.Threading.DispatcherTimer
    $timer.Interval = [TimeSpan]::FromMilliseconds(500)
    $timer.Add_Tick({
        $wert = [Environment]::GetEnvironmentVariable("Installation", "User")
        if ($wert -eq "FINISH")
        {
            [Environment]::SetEnvironmentVariable("Installation", $null, "User")
            $timer.Stop()
            $global:Window.Close()
        }
    })
    $timer.Start()
}

方案优势

  • 无闪烁:BitmapImage加载GIF时会缓存帧,切换或循环时不会出现源重置导致的闪烁
  • 无需手动循环:GIF的动画循环由WPF内置处理,无需监听MediaEnded事件手动重置
  • 更稳定:避免了MediaElement对GIF支持的兼容性问题
备选方案:修复MediaElement的循环逻辑

如果必须使用MediaElement,可以尝试在MediaEnded事件中通过Dispatcher异步重置位置,确保操作在UI线程执行:

$Load_Loader_gpl.add_MediaEnded({
    $wert = [Environment]::GetEnvironmentVariable("Installation", "User")
    if ($wert -eq "FINISH")
    {
        [Environment]::SetEnvironmentVariable("Installation", $null, "User")
        $global:Window.Close()
    }
    else
    {
        # 使用Dispatcher异步执行重置,确保在UI线程操作
        $Load_Loader_gpl.Dispatcher.InvokeAsync({
            $Load_Loader_gpl.Stop()
            $Load_Loader_gpl.Seek([TimeSpan]::Zero, [System.Windows.Media.MediaSeekMode]::FrameNearest)
            $Load_Loader_gpl.Play()
        })
    }
})

注意:此方案仍可能存在部分GIF循环失效的情况,不如Image控件方案稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:50:56