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

2022-12-01 15:54:20 浏览数 (3)

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

0 人点赞