首页 > 其他分享 >MAUI Blazor学习17-NavigationLock阻止页面回退

MAUI Blazor学习17-NavigationLock阻止页面回退

时间:2024-08-11 20:39:41浏览次数:8  
标签:NavigationLock cnblogs 17 博客园 SunnyTrudeau MAUI Blazor com

MAUI Blazor学习17-NavigationLock阻止页面回退

 

MAUI Blazor系列目录

  1. MAUI Blazor学习1-移动客户端Shell布局 - SunnyTrudeau - 博客园 (cnblogs.com)
  2. MAUI Blazor学习2-创建移动客户端Razor页面 - SunnyTrudeau - 博客园 (cnblogs.com)
  3. MAUI Blazor学习3-绘制ECharts图表 - SunnyTrudeau - 博客园 (cnblogs.com)
  4. MAUI Blazor学习4-绘制BootstrapBlazor.Chart图表 - SunnyTrudeau - 博客园 (cnblogs.com)
  5. MAUI Blazor学习5-BLE低功耗蓝牙 - SunnyTrudeau - 博客园 (cnblogs.com)
  6. MAUI Blazor学习6-扫描二维码 - SunnyTrudeau - 博客园 (cnblogs.com)
  7. MAUI Blazor学习7-实现登录跳转页面 - SunnyTrudeau - 博客园 (cnblogs.com)
  8. MAUI Blazor学习8-支持多语言 - SunnyTrudeau - 博客园 (cnblogs.com)
  9. MAUI Blazor学习9-VS Code开发调试MAUI入门 - SunnyTrudeau - 博客园 (cnblogs.com)
  10. MAUI Blazor学习10-BarcodeScanner扫描二维码 - SunnyTrudeau - 博客园 (cnblogs.com)
  11. MAUI Blazor学习11-百度地图定位 - SunnyTrudeau - 博客园 (cnblogs.com)
  12. MAUI Blazor学习12-文件另存为 - SunnyTrudeau - 博客园 (cnblogs.com)
  13. MAUI Blazor学习13-打开文件 - SunnyTrudeau - 博客园 (cnblogs.com)
  14. MAUI Blazor学习14-选择目录 - SunnyTrudeau - 博客园 (cnblogs.com)
  15. MAUI Blazor学习15-采用html2pdf.js生成pdf - SunnyTrudeau - 博客园 (cnblogs.com)
  16. MAUI Blazor学习16-连续按BACK退出APP - SunnyTrudeau - 博客园 (cnblogs.com)

 

在APP功能开发中,有时候要阻止页面回退,比如,当前填写的内容没有保存,长时间运行的任务没有完成等等。本来想着拦截BACK按键事件来实现,后来发现MAUI Blazor有现成的组件NavigationLock,可以非常简单的实现阻止页面回退的功能。参考微软官网:

https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-8.0#handleprevent-location-changes

只要呈现导航事件,NavigationLock 组件就会将其拦截,除非决定继续或取消,否则将一直有效“锁定”任何给定的导航。 当导航拦截的范围可以限定为组件的生存期时,使用 NavigationLock。

NavigationLock 参数:

ConfirmExternalNavigation 设置浏览器对话框以提示用户确认或取消外部导航。 默认值为 false。 显示确认对话框需要在使用浏览器地址栏中的 URL 触发外部导航之前与页面进行初始用户交互。 有关交互要求的详细信息,请参阅 Window:beforeunload 事件(MDN 文档)。

OnBeforeInternalNavigation 为内部导航事件设置回调。

 

基于MaBlaApp项目,添加NavigationLock组件阻止页面回退功能。模拟实现一个需求,当前页面正在运行长时间任务,需要首先停止任务,才能退出页面。

D:\Software\gitee\mauiblazorapp\MaBlaApp\Pages\LongTimeTask.razor

 

@page "/longtimetask"

<h3>阻止长时间任务页面回退</h3>

<div class="d-flex justify-content-between m-1">
    <button class="btn btn-primary mx-2 @BtnStartCss" @onclick=StartTaskAsync>开始长时间任务</button>
    <button class="btn btn-danger mx-2 @BtnStopCss" @onclick=@(() => StopTaskAsync(false))>停止长时间任务</button>
</div>
<p class="m-1">任务进度:@ProcessMsg</p>
<div class="progress m-1" style="height:10px">
    <div class="progress-bar bg-primary" style="width:@Process%"></div>
</div>

<NavigationLock ConfirmExternalNavigation="true" OnBeforeInternalNavigation="OnBeforeInternalNavigation" />

@code {
    private string BtnStartCss => IsBusy ? "disabled" : "";
    private string BtnStopCss => IsBusy ? "" : "disabled";

    private bool IsBusy = false;
    private CancellationTokenSource Cts;

    private int Process = 0;
    private string ProcessMsg = "";

    //开始长时间任务
    private async Task StartTaskAsync()
    {
        if (IsBusy)
            return;

        if (Cts is not null)
            return;

        try
        {
            IsBusy = true;
            Cts = new CancellationTokenSource();

            var startTime = DateTimeOffset.Now;

            Process = 0;
            ProcessMsg = "...";
            StateHasChanged();

            using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
            while (await timer.WaitForNextTickAsync(Cts.Token))
            {
                Process += 10;

                ProcessMsg = $"耗时{DateTimeOffset.Now.Subtract(startTime).TotalSeconds:N0}秒,进度{Process}%";
                StateHasChanged();

                if (Process >= 100)
                {
                    ProcessMsg += ",任务圆满完成";
                    break;
                }
            }
        }
        catch (OperationCanceledException)
        {
            ProcessMsg += ",任务提前终止";
            System.Diagnostics.Debug.WriteLine($"{DateTimeOffset.Now:G}, {ProcessMsg}");
        }
        finally
        {
            Cts.Dispose();
            Cts = null;
            IsBusy = false;
        }

        StateHasChanged();
    }

    //停止长时间任务
    private async Task StopTaskAsync(bool forceStop = false)
    {
        if (!IsBusy)
            return;

        if (!forceStop)
        {
            //询问用户是否结束任务
            bool isStopTask = await App.Current.MainPage.DisplayAlert("警告", "任务进行中,是否结束任务?", "结束任务", "继续任务");
            if (!isStopTask)
                return;
        }

        if (Cts is not null)
            Cts.Cancel();
    }

    //检查能否安全退出页面
    private async Task OnBeforeInternalNavigation(LocationChangingContext context)
    {
        //如果当前任务正在运行中,请用户先停止任务,才能退出页面
        if (IsBusy)
        {
            bool isStopTask = await App.Current.MainPage.DisplayAlert("警告", "任务进行中,是否结束任务?", "结束任务", "继续任务");

            if (isStopTask)
            {
                //强制结束任务
                await StopTaskAsync(true);
            }
            else
            {
                //阻止页面退出
                context.PreventNavigation();
            }
        }
    }
}

 

在VS2022自带的安卓模拟器上调试运行,开始长时间任务后,点击BACK键退出页面,弹窗询问用户,如果选择继续任务,则阻止页面退出,测试效果符合预期。

DEMO代码地址:https://gitee.com/woodsun/mauiblazorapp

 

标签:NavigationLock,cnblogs,17,博客园,SunnyTrudeau,MAUI,Blazor,com
From: https://www.cnblogs.com/sunnytrudeau/p/18341858

相关文章

  • WPS Office 2023专业版 v12.8.2.17149v2 精简优化版
    概述WPSOffice是由金山软件股份有限公司自主研发的一款办公软件套装,可以实现办公软件最常用的文字、表格、演示等多种功能。具有内存占用低、运行速度快、体积小巧、强大插件平台支持、免费提供海量在线存储空间及文档模板、支持阅读和输出PDF文件、全面兼容微软Office97-2010格......
  • CSP17
    请注意:题目背景与题目可能没有关系第一题,性质题,找到序列的最大值与最小值,我们发现如果只有正数的话和只有负数的话都很好处理,正数正序处理类似前缀加,负数后缀加,那如果正负都有,该怎么办呢?其实我们可以吧序列全变为正的或负的吧,但是需要比较一下最大值最小值,如果都变成正的话,对......
  • 分享一套包含12000多条历史上的今天发生的大事件数据库 及中国城市2017年全年GDP排行
    一、分享一套包含12000多条历史上的今天发生的大事件数据库    分享一套包括1.2万条历史上的今天的sql数据库文件。包含12000多条历史上的今天数据的SQL数据库文件.zip。详细数据可以参考使用此数据库运行的网站: http://www.guihei.com 下    资源下载链......
  • 新手常见错误:Language level is invalid or missing in pom.xml. Current project JDK
    目录Blue留声机:分析报错 Blue留声机:今天开一个maven的时候遇到这样一个报错,这个报错对于我来言是一个并不陌生的报错,早期学习spring框架的时候,遇到过这个问题,当时怎么也弄不出来(现在想想那个时候的我真菜),现在却对这种问题的解决游刃有余。好了,不多bb了,看看我一般处理bu......
  • ISO 26262中的失效率计算:IEC TR 62380-Section 17-Displays, solid state lamps
    目录概要1元器件分类2显示器失效率的计算2.1Displays失效率预测模型2.2Base失效率2.3温度循环De-rating系数3固态灯失效率的计算3.1Solidstatelamps失效率预测模型2.2温度循环De-rating系数概要IECTR62380《电子组件、PCBs和设备的可靠性预计通用模型......
  • [赛记] 暑假集训CSP提高模拟17
    符号化方法初探100pts签到题?做了得有1.5h+;考虑全是正数或全是负数的情况,那么我们可以对其做一次类似于前缀和或后缀和的操作,需要$n-1$次;所以我们只需将数列中的数全部转化成正数或负数即可,具体地,找出所有正数的和和所有负数的和,如果前者比后者要大,那么就将所有正数加起......
  • C++17新特性
    C++17新特性语言特性使用auto声明非类型模板参量折叠表达式提供模板参数包的折叠template<typename...Args>boollogicalAnd(Args...args){//二元折叠return(true&&...&&args);}boolb=false;bool&b2=b;logicalAnd(b,b2,true);//==fa......
  • [ARC179E] Rectangle Concatenation
    MyBlogs[ARC179E]RectangleConcatenation唐完了。稍微观察一下发现矩形只有两种形态。考虑暴力:从每个\(i\)开始向后扫,设\(f_{j,0}\)表示能否拼在左右,\(f_{j,1}\)表示能否拼在上下。设\(S_{l,r}\)表示\([l,r]\)内矩形的面积和,没想到用面积判就败了:\[\begin{aligned......
  • 暑假集训CSP提高模拟17
    \[暑假集训CSP提高模拟\operatorname{EIJ}_{2}(6)-1\]\(\operatorname{EIJ}_{k}(A)\)定义为有\(A\)个球,\(k\)个盒子,盒子相同,球不同,把全部球放入的方案数Hint易知\(\operatorname{EIJ}_k(A)=\dfrac{A^k}{k!}\),详见这篇文章其实我觉得构造的过程更有意思:对一个给定的正......
  • 暑假集训csp提高模拟17
    赛时rank16,T1100,T250,T325,T425T4是简单题,但因为转移方程没有继承上一位状态,然后就挂了T3写了个神秘的状压,打了25的部分分T2暴力,T1正解T1符号化方法初探[ABC081D]Non-decreasing考虑最大值和最小值若\(abs(max)>abs(min)\),则将所有的负数加上最大值使其变为正,前缀......