前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始搭建一个GIS开发小框架(九)——WPF进度条效果

从零开始搭建一个GIS开发小框架(九)——WPF进度条效果

作者头像
天堂向左
发布2022-12-01 15:54:20
5530
发布2022-12-01 15:54:20
举报
文章被收录于专栏:天堂向左程序员向右

1

概述

Introduction to new functions

今天借GIS项目实现一个进度条效果,这个效果在各种管理系统中是最常见的一个效果,特别是在处理某个任务消耗的时间过长的场景,可以避免UI假死,提高用户体验。我这次用的POI数据大概有90W条,这个目录树是我为了练手,故意拆成五层的,其实从第三层到第五层原本是放在一个字段里的string型POI类型描述,将它拆解成三层树结构时损耗了部分性能,到最下面一层(图标是感叹号)类型,大概有5700多个叶子节点,加载这个资源目录树需要一段时间,这里用委托实现页面传值+BackgroundWorker实现异步弹框进度条效果。我原来在winform里面实现过,但是WPF框架里还没做过,拿这个练练手,为今后的工(qiu)作(zhi)任(mian)务(shi)做好技术储备。

委托是一种引用类型,它是函数指针的托管版本。

2

功能实现

Function

废话不多说直接上图。示例只用了一个区的数据,读取全市数据太慢了。

http://mpvideo.qpic.cn/0bc3b4an2aaakmam7zdkbnrvad6d3uhqbxia.f10002.mp4?dis_k=e7829d8870a9a1e26d46f36d5369b94f&dis_t=1669881228&vid=wxv_2655894180405231616&format_id=10002&support_redirect=0&mmversion=false

3

核心功能代码

Code

委托页面传值是委托的一个最简单应用场景,大家可以拿来练练手,边做边理解一下委托的概念,我把委托传值用法的大致思路画了一个草稿,见下图,希望对大家理解有帮助。代码最后那个“百分比处理”的代码是我在网上copy的一个觉得比较别致的写法,纯属收藏,实际处理百分比不需要那么啰嗦,求x的时候不乘以100,直接加上百分符号就完事了。

弹框代码示例

代码语言:javascript
复制
// 文本框赋值方法 的委托属性
private LoadDataEventHandler _loadDataSubWindowDel;
BackgroundWorker worker = null;

/// <summary>
/// 
/// </summary>
/// <param name="typeString"></param>
/// <param name="adname"></param>
/// <param name="del"></param>
public WindowForDataLoadProcess(string typeString, string adname, LoadDataEventHandler del)
{
    InitializeComponent();

    worker = new BackgroundWorker();
    //异步取消 需要增加这个 不然取消失效
    worker.WorkerSupportsCancellation = true;
    //支持报告进度
    worker.WorkerReportsProgress = true;
    //注册滚动条事件
    worker.ProgressChanged += ProgessChangedInit;
    //注册任务
    worker.DoWork += DoWorkInit;
    //任务完毕触发
    worker.RunWorkerCompleted += CompleteWorkInit;

    StartKeyCompareRunning(typeString, adname);   //这个是我的启动方法
    this._loadDataSubWindowDel = del;
}

#region BackgroundWorker 多线程

/// <summary>
/// 第一次打开Form
/// </summary>
private void StartKeyCompareRunning(string typeString, string adname)
{
    string[] para = { typeString, adname };
    worker.RunWorkerAsync(para);
}

//调用 RunWorkerAsync 时发生
public void DoWorkInit(object sender, DoWorkEventArgs e)
{
    if (worker.CancellationPending) //判断是否取消操作
    {
        e.Cancel = true; //这里才真正取消 
        return;
    }
    else
    {
        string[] receive = e.Argument as string[];
        e.Result = LoadData(worker, e, receive);   //LoadData就是读取数据并处理进度条report事件的自定义方法
    }
}

//调用 ReportProgress 时发生
public void ProgessChangedInit(object sender, ProgressChangedEventArgs e)
{
    //将异步任务进度的百分比赋给进度条
    this.progressBar1.Value = e.ProgressPercentage;
    this.Label1.Content = (string)e.UserState;
}

/// <summary>
/// 当后台操作已完成、被取消或引发异常时发生
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void CompleteWorkInit(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        System.Windows.MessageBox.Show("Progess is interrupted!");
    }
    else if (e.Error != null)
    {
        System.Windows.MessageBox.Show("Worker exception: " + e.Error.ToString());
    }
    else
    {
        try
        {
            FormMainProgressBarResult re = (FormMainProgressBarResult)e.Result;
            this.Close();

            //委托返回值给父窗口
            _loadDataSubWindowDel(re);  //委托传值回主界面
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

#region load数据

/// <summary>
/// 组装树的数据集
/// </summary>
private FormMainProgressBarResult LoadData(BackgroundWorker worker, DoWorkEventArgs e, string[] paraArray)
{
    FormMainProgressBarResult iRel = new FormMainProgressBarResult();

    try
    {
        组装DataTable dtLevel5 数据集(方法略),dtLevel5是第五层叶子节点
        
        dtLevel5 装进dt里,dt是总数据集
    foreach (DataRow d5 in dtLevel5.Rows)
    {
      DataRow dr5 = dt.NewRow();
      dr5["id"] = d5["Name"];
      .....
      dt.Rows.Add(dr5);  
    }
    
        //进度条计算
        index = index + dtLevel5.Rows.Count;
        int x = (int)Math.Floor((double)((index + 1) * 100 / AllRows));
        //百分比处理
        System.Globalization.NumberFormatInfo provider = new System.Globalization.NumberFormatInfo();
        provider.PercentDecimalDigits = 0;//小数点保留几位数.
        provider.PercentPositivePattern = 0;//百分号出现在何处.
        double result = (double)x/100;//一定要用double类型.
        report_message = result.ToString("P", provider);

        worker.ReportProgress(x, report_message);

        组装dt完毕后放进返回值
    
        iRel.ResultDataTable = dt;
        iRel.ResultString = "ok";
        iMsgRel = 1;
        return iRel;
    }
    catch (Exception ex)
    {
        iRel.ResultDataTable = null;
        iRel.ResultString = ex.Message;
        return iRel;
    }

}
#endregion
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天堂向左程序员向右 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档