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

MAUI Android:GoToAsync跳转后主页图片点击仅首次生效求助

问题分析与解决方案

问题根源

  1. TaskCompletionSource未触发完成:MainViewModel中的SelectNoteImage_2_Taps方法创建了TaskCompletionSource并等待其完成,但从拍照页面返回时,从未调用tcs.SetResult(),导致该任务永久挂起。
  2. RelayCommand默认禁止并发执行:由于首次调用的任务未完成,后续点击触发的RelayCommand因默认AllowConcurrentExecution=false而被阻塞,无法执行。
  3. UI线程阻塞:挂起的任务占用UI线程,导致后续点击无响应,同时出现“Debug: Android: Unable to find click target.”的调试输出。

修复方案

方案一:移除TaskCompletionSource,使用Shell导航参数传递结果(推荐)

这种方式符合MAUI Shell的导航设计规范,解耦ViewModel与页面,避免耦合性问题。

修改MainViewModel.cs代码

[RelayCommand]
public async Task SelectNoteImage_2_Taps(object o)
{
    var note = o as Note;
    if (note == null) return;

    // 传递当前Note到拍照页面(可选,根据需求调整)
    var navParams = new Dictionary<string, object>
    {
        ["CurrentNote"] = note
    };

    // 导航并接收返回结果
    var result = await Shell.Current.GoToAsync(nameof(TakeCopyPhotosPage), navParams);
    
    // 处理返回的图片路径
    if (result.TryGetValue("ImagePath", out var imagePathObj) && imagePathObj is string imagePath)
    {
        note.ItemImagePath = string.IsNullOrEmpty(imagePath) ? defaultphotoImagePath : imagePath;
        ItemImagePath = note.ItemImagePath;
    }
}

修改TakeCopyPhotosPage.xam.cs代码

private async void SavePhoto_Clicked(object sender, EventArgs e)
{
    string filepath = NotesApp.NotesStorageManager.NotesImagesSubFolderFullPath;
    if (string.IsNullOrEmpty(entry.Text)) return;
    
    string imagename = entry.Text + ".png";
    filepath = Path.Combine(filepath, imagename); // 用Path.Combine避免路径拼接错误

    await cameraView.SaveSnapShot(Camera.MAUI.ImageFormat.PNG, filepath);
    
    // 传递图片路径作为返回参数
    var returnParams = new Dictionary<string, object>
    {
        ["ImagePath"] = filepath
    };
    
    // 返回主页并传递结果
    await Shell.Current.GoToAsync("..", returnParams);
}

方案二:临时修复TaskCompletionSource(耦合性高,不推荐)

如果需要快速验证问题,可以在拍照页面返回前触发TaskCompletionSource的完成信号,但这种方式会让页面直接依赖ViewModel,不符合MVVM设计原则。

修改TakeCopyPhotosPage.xam.cs代码

private async void SavePhoto_Clicked(object sender, EventArgs e)
{
    // ... 原保存照片代码 ...

    mainViewModel.ItemImagePath = filepath;
    // 触发TaskCompletionSource完成
    mainViewModel.tcs?.SetResult();
    await Shell.Current.GoToAsync("..");
}

注意:需要将MainViewModel中的tcs字段改为public,或者添加公开的触发方法,这种方式不推荐长期使用。

额外优化点

  1. 将SavePhoto_Clicked的async void改为async Task(事件处理中允许async void,但async Task更便于异常处理):
private async Task SavePhoto_Clicked(object sender, EventArgs e)
{
    // ... 原代码 ...
}

然后在XAML中绑定命令(推荐用RelayCommand替代事件处理,进一步符合MVVM)。

  1. 检查GestureRecognizer的绑定,确保命令能正确触发:
<Image>
    <Image.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding SelectNoteImage_2_TapsCommand}" CommandParameter="{Binding .}" />
    </Image.GestureRecognizers>
</Image>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 13:10:20