C# UWP应用:点击按钮加载图片时显示ProgressRing
UWP中实现图片加载时显示ProgressRing的完整方案
嘿,这个需求在UWP里实现起来挺顺畅的,核心思路就是监听图片的加载状态,在开始加载时激活ProgressRing,加载完成(或失败)后关闭它。我给你分步骤说明,附完整代码示例:
1. 先搞定XAML布局
首先在页面里放置需要的控件:Image(你说的PictureBox在UWP里对应这个)、ProgressRing和切换按钮。把ProgressRing放在Image的正上方,默认不激活:
<Grid> <!-- 用于显示图片的控件 --> <Image x:Name="DisplayImage" Width="400" Height="300" Stretch="Uniform"/> <!-- 加载进度环,默认隐藏(IsActive=false) --> <ProgressRing x:Name="LoadingRing" Width="50" Height="50" IsActive="False" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF0078D7"/> <!-- 可以自定义进度环颜色 --> <!-- 下一张按钮 --> <Button x:Name="NextButton" Content="下一张" Click="NextButton_Click" HorizontalAlignment="Bottom" Margin="0,0,0,20"/> </Grid>
2. 后台C#逻辑实现
我们需要维护一个图片路径列表,点击按钮时切换图片,同时通过BitmapImage的ImageOpened和ImageFailed事件来控制进度环:
using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Imaging; using System; using System.Collections.Generic; using Windows.UI.Popups; namespace YourAppNamespace { public sealed partial class MainPage : Page { // 存储所有图片的路径 private List<string> _imagePaths; // 当前显示的图片索引 private int _currentImageIndex = -1; public MainPage() { this.InitializeComponent(); // 初始化图片路径——这里假设图片放在项目的Assets文件夹,命名为Image1到Image10 _imagePaths = new List<string>(); for (int i = 1; i <= 10; i++) { _imagePaths.Add($"ms-appx:///Assets/Image{i}.png"); } } private void NextButton_Click(object sender, RoutedEventArgs e) { // 更新索引,循环显示图片 _currentImageIndex = (_currentImageIndex + 1) % _imagePaths.Count; // 先激活进度环,告诉用户正在加载 LoadingRing.IsActive = true; // 创建BitmapImage来加载图片 var bitmap = new BitmapImage(); // 绑定加载完成和失败的事件 bitmap.ImageOpened += OnImageLoaded; bitmap.ImageFailed += OnImageLoadFailed; // 设置图片源,开始异步加载 bitmap.UriSource = new Uri(_imagePaths[_currentImageIndex]); DisplayImage.Source = bitmap; } private void OnImageLoaded(object sender, RoutedEventArgs e) { // 图片加载完成,关闭进度环 LoadingRing.IsActive = false; // 移除事件监听,避免内存泄漏 CleanupBitmapEvents(sender as BitmapImage); } private void OnImageLoadFailed(object sender, ExceptionRoutedEventArgs e) { // 图片加载失败,也要关闭进度环,还可以给用户提示 LoadingRing.IsActive = false; CleanupBitmapEvents(sender as BitmapImage); // 弹出错误提示(可选) _ = new MessageDialog($"图片加载失败:{e.ErrorMessage}").ShowAsync(); } private void CleanupBitmapEvents(BitmapImage bitmap) { if (bitmap != null) { bitmap.ImageOpened -= OnImageLoaded; bitmap.ImageFailed -= OnImageLoadFailed; } } } }
3. 额外优化建议(MVVM架构适配)
如果你的应用是采用MVVM架构的,更推荐用数据绑定来控制ProgressRing,这样代码更解耦:
ViewModel示例(需实现INotifyPropertyChanged)
using System.ComponentModel; using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Popups; using System.Net.Http; using System.Threading.Tasks; public class MainViewModel : INotifyPropertyChanged { private List<string> _imagePaths; private int _currentIndex = -1; private bool _isLoading; private BitmapImage _currentImage; public bool IsLoading { get => _isLoading; set { _isLoading = value; OnPropertyChanged(nameof(IsLoading)); } } public BitmapImage CurrentImage { get => _currentImage; set { _currentImage = value; OnPropertyChanged(nameof(CurrentImage)); } } public MainViewModel() { _imagePaths = new List<string>(); for (int i = 1; i <= 10; i++) { _imagePaths.Add($"ms-appx:///Assets/Image{i}.png"); } } public async Task LoadNextImage() { IsLoading = true; try { _currentIndex = (_currentIndex + 1) % _imagePaths.Count; var bitmap = new BitmapImage(); // 如果是网络图片,可以用SetSourceAsync等待加载完成 if (_imagePaths[_currentIndex].StartsWith("http")) { using var client = new HttpClient(); var stream = await client.GetStreamAsync(_imagePaths[_currentIndex]); await bitmap.SetSourceAsync(stream.AsRandomAccessStream()); } else { bitmap.UriSource = new Uri(_imagePaths[_currentIndex]); } CurrentImage = bitmap; } catch (Exception ex) { _ = new MessageDialog($"加载失败:{ex.Message}").ShowAsync(); } finally { IsLoading = false; } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
对应的XAML绑定(需先在资源中声明ViewModel)
<Page.Resources> <local:MainViewModel x:Key="MainViewModel"/> </Page.Resources> <Grid DataContext="{StaticResource MainViewModel}"> <Image Source="{Binding CurrentImage}" Width="400" Height="300" Stretch="Uniform"/> <ProgressRing IsActive="{Binding IsLoading}" Width="50" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Button Content="下一张" Click="async (s,e) => await ((MainViewModel)DataContext).LoadNextImage()" HorizontalAlignment="Bottom" Margin="0,0,0,20"/> </Grid>
注意事项
- 如果图片是从网络加载的,记得在
Package.appxmanifest里勾选**Internet(Client)**权限,否则会加载失败。 - 图片路径要确保正确:本地资源用
ms-appx:///前缀,本地文件用ms-appdata:///前缀。
内容的提问来源于stack exchange,提问作者Ashkan
相关产品推荐
相关产品推荐

