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

MAUI中ViewModel内修改IsLoading绑定未正常生效求助

问题:加载动画绑定的IsLoading变量未正常生效

在ViewModel中调用异步方法时,通过布尔变量IsLoading控制UI加载动画,但设置IsLoading = true后加载动画不显示,方法执行完成后IsLoading = false也未正常更新UI状态。


相关代码片段

LoadFileNames方法

public async Task LoadFileNames(string engineIdentifier, int displayMode) {
try {
    ImageList.Clear();
    IsLoading = true;
    await MergeFiles(engineIdentifier);

    IsLoading = false;
    ...
}

ViewModel中IsLoading的实现

private bool _isLoading;
public bool IsLoading {
    get { return _isLoading; }
    set {
        _isLoading = value;
        OnPropertyChanged();
    }
}

public void OnPropertyChanged([CallerMemberName] string name = null) =>
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

视图绑定代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         Shell.BackgroundColor="#696969"
         xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
         xmlns:converters="clr-namespace:EngineCheck.Converters"
         x:Class="EngineCheck.Views.EngineView"
         xmlns:vm="clr-namespace:EngineCheck.ViewModels">

    <ContentPage.BindingContext>
        <vm:EngineViewModel x:Name="viewmodel"/>
    </ContentPage.BindingContext>

加载动画控件

<ActivityIndicator IsRunning="{Binding IsLoading}" IsVisible="{Binding IsLoading}"/>

更新:MergeFiles及MergeBmpAndSvg方法

private async Task MergeFiles(string engineIdentifier) {
    try {
        string folderPath = prefs.Get("images_save_location", "");
        string searchString = engineIdentifier;
        if(Directory.Exists(folderPath)) {
            string[] files = Directory.GetFiles(folderPath);
            foreach(string filePath in files) {
                string fileName = Path.GetFileName(filePath);
                if(fileName.EndsWith("bmp") && 
                    fileName.Contains(searchString)) {
                        Utilities.Utilities.MergeBmpAndSvg(folderPath, 
                            fileName[..^4]);
                    }
            }
        } else {
        //TODO
        }
    } catch(Exception ex) {
        logger.Error(ex.Message);
    }
}
public static void MergeBmpAndSvg(string path, string filename) {
    try {
        Bitmap bmpImage = new Bitmap(path + "/" + filename + ".bmp");
        SvgDocument svgDocument = SvgDocument.Open(path + "/" + filename +         
            ".svg");
        Bitmap svgBitmap = svgDocument.Draw();
        Bitmap resultImage = new Bitmap(bmpImage.Width, bmpImage.Height);
        using(Graphics graphics = Graphics.FromImage(resultImage)) {
            graphics.DrawImage(bmpImage, 0, 0);
            graphics.DrawImage(svgBitmap, new System.Drawing.Point(0, 0));
        }
        resultImage.Save(path + "/" + filename + ".png");
        bmpImage.Dispose();
        svgBitmap.Dispose();
        resultImage.Dispose();
    } catch(Exception ex) {
        logger.Error(ex.Message);
    }
}

问题根源

MergeFiles方法虽标记为async,但内部无任何await异步操作,本质是同步阻塞UI线程。设置IsLoading = true后,UI线程立刻被文件IO、图片处理等同步操作卡住,没时间更新UI显示加载动画;同步操作完成后IsLoading又被立即设为false,导致用户看不到加载动画的状态变化。

此外,MergeBmpAndSvg是纯同步的图片处理方法,进一步加剧了UI线程的阻塞。


解决方案

方案1:将同步操作移至后台线程

修改MergeFiles,把耗时的同步逻辑包装到Task.Run中,让其在后台线程执行,释放UI线程更新加载状态:

private async Task MergeFiles(string engineIdentifier) {
    try {
        string folderPath = prefs.Get("images_save_location", "");
        string searchString = engineIdentifier;
        if(Directory.Exists(folderPath)) {
            // 将文件遍历和图片处理放到后台线程
            await Task.Run(() => {
                string[] files = Directory.GetFiles(folderPath);
                foreach(string filePath in files) {
                    string fileName = Path.GetFileName(filePath);
                    if(fileName.EndsWith("bmp") && 
                        fileName.Contains(searchString)) {
                            Utilities.Utilities.MergeBmpAndSvg(folderPath, 
                                fileName[..^4]);
                        }
                }
            });
        } else {
        //TODO
        }
    } catch(Exception ex) {
        logger.Error(ex.Message);
    }
}

方案2:优先使用异步API(更推荐)

替换同步方法为异步版本,比如文件IO用Directory.GetFilesAsync,减少手动线程包装的开销:

private async Task MergeFiles(string engineIdentifier) {
    try {
        string folderPath = prefs.Get("images_save_location", "");
        string searchString = engineIdentifier;
        if(Directory.Exists(folderPath)) {
            // 使用异步文件遍历API
            string[] files = await Directory.GetFilesAsync(folderPath);
            foreach(string filePath in files) {
                string fileName = Path.GetFileName(filePath);
                if(fileName.EndsWith("bmp") && 
                    fileName.Contains(searchString)) {
                        // 图片处理仍需后台执行,避免阻塞UI
                        await Task.Run(() => Utilities.Utilities.MergeBmpAndSvg(folderPath, fileName[..^4]));
                    }
            }
        } else {
        //TODO
        }
    } catch(Exception ex) {
        logger.Error(ex.Message);
    }
}

额外注意事项

  • 确认ViewModel已正确实现INotifyPropertyChanged接口(代码中已实现,XAML绑定通常会自动订阅PropertyChanged事件)。
  • MergeBmpAndSvg涉及大量内存操作,在后台线程执行时需注意资源释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:42:08