Gif演示

分解步骤

1,使用组件DataGridView

2,使用DataSource来控制表格展示的数据来源(注意:来源需要是DataTable类型)

3,需要用到异步线程。如果是不控制数据源的话,需要使用UI安全线程;(使用Control.Invoke或Control.BeginInvoke方法)

4,DataGridView的列如果设置图片,尽量代码设置

5,DataTable类型也是可以使用LINQ的,参考:AsEnumerable

完整代码

using Newtonsoft.Json;
using Sunny.UI.Win32;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WinApp.i18n;
using WinApp.Until;
using WinApp.ViewModel;
using static System.Net.Mime.MediaTypeNames;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Security.Cryptography; namespace WinApp.View
{
public partial class DownloadList : UserControl
{
/// <summary>
/// 开启任务的开关(作用:禁止重复启动任务)
/// </summary>
private static bool _taskSwitch = true;
/// <summary>
/// 任务中的小开关(作用:如果被外部干涉,则进行退出执行任务内容)
/// </summary>
private static bool _taskCondition = true; public DataTable _table;
List<DownloadListDto> _mainList; public UILabel _lbNotData; public DownloadList()
{
InitializeComponent();
var mainTitle = string.Empty;
mainTitle = Language.GetLang("downloadTitle1");
mainTitle += "\r" + Language.GetLang("downloadTitle2");
this.uiPanel1.Text = mainTitle; uiDataGridView1.ColumnHeadersVisible = false;
uiDataGridView1.RowTemplate.Height = 65;
uiDataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None; _lbNotData = new UILabel();
_lbNotData.Text = "No more data available";
_lbNotData.Cursor = Cursors.Hand;
_lbNotData.TextAlign = ContentAlignment.MiddleCenter;
_lbNotData.Location = new Point(450, 50);
_lbNotData.Width = 200;
_lbNotData.Visible = false;
this.uiPanel2.Controls.Add(_lbNotData);
} private void DownloadList_Load(object sender, EventArgs e)
{
QueryData();
} public void SetCondition(bool setValue)
{
_taskCondition = setValue;
}
public async Task DownloadAllAsync()
{
if (_taskSwitch)
{
if (_table.Rows.Count <= 0)
{
UIMessageDialog.ShowMessageDialog("No more data available", UILocalize.WarningTitle, showCancelButton: false, UIStyle.Orange, false);
return;
} //已经执行,请勿重复执行;
_taskSwitch = false; foreach (DataRow row in _table.Rows)
{
row["Status"] = "2";//设置为下载中的状态
uiDataGridView1.Refresh();
} while (_table.Rows.Count > 0 && _taskCondition)
{//如果列表有数据就一直循环进行下载删除
var firstRow = _table.Rows[0];
if (firstRow == null)
{//第一个元素等于NULL
return;
} for (int j = 0; j <= 100; j++)//模拟进度条
{
if (_taskCondition)
{//如果没有暂停
await Task.Delay(10); // wait for 100 milliseconds
firstRow["DownloadProgress"] = j.ToString(); }
else
{//暂停
firstRow["Status"] = "1";
}
} if (_taskCondition)
{
// 获取当前行的数据行
var _Id = (int)firstRow["Id"];
// 使用Linq查询匹配的行
var rowsToDelete = _table.AsEnumerable().FirstOrDefault(row => row.Field<int>("Id") == _Id);
_table.Rows.Remove(rowsToDelete);
}
} //foreach (DataRow row in _table.Rows)
//{
// row["Status"] = "2"; // for (int j = 0; j <= 100; j++)
// {
// if (_taskCondition)
// {
// await Task.Delay(10); // wait for 100 milliseconds
// row["DownloadProgress"] = j.ToString();
// }
// else
// {
// row["Status"] = "1";
// }
// }
// // 获取当前行的数据行
// var _Id = (int)row["Id"];
// // 使用Linq查询匹配的行
// var rowsToDelete = _table.AsEnumerable().FirstOrDefault(row => row.Field<int>("Id") == _Id);
// _table.Rows.Remove(rowsToDelete);
//} //foreach (var item in _mainList)
//{
// item.Status = 2;
// uiDataGridView1.Refresh(); // for (int i = 0; i < 100; i++)
// {
// if (_taskCondition)
// {
// await Task.Delay(100); // wait for 100 milliseconds
// item.DownloadProgress = i.ToString();
// uiDataGridView1.Refresh();
// }
// else
// {
// item.Status = 1;
// return;
// }
// }
//} //执行完毕,则可以重新执行
_taskSwitch = true;
}
else
{
//因为此次没有执行,下次允许执行;
_taskSwitch = true;
return;
}
} public void PauseAll()
{
SetCondition(false); //获取所有已经开始的数据 var pauseList = _table.AsEnumerable().Where(row => row.Field<int>("Status") == 2);
foreach (DataRow item in pauseList)
{
item["Status"] = "1";
uiDataGridView1.Refresh();
} } public void DeleteAll()
{
SetCondition(false); // 清除所有行
_table.Clear();
uiDataGridView1.Refresh();
this.uiDataGridView1.Refresh();
} public void QueryData()
{ LoadingHelper.ShowLoadingScreen(); _mainList = new List<DownloadListDto>();
_mainList.Add(new DownloadListDto()
{
Id = 1,
Title = "A1" + Environment.NewLine + "B1",
Status = 1,
DownloadProgress = "0"
});
_mainList.Add(new DownloadListDto()
{
Id = 2,
Title = "A2" + Environment.NewLine + "B2",
Status = 1,
DownloadProgress = "0"
});
_mainList.Add(new DownloadListDto()
{
Id = 3,
Title = "A3" + Environment.NewLine + "B3",
Status = 1,
DownloadProgress = "0"
});
_mainList.Add(new DownloadListDto()
{
Id = 4,
Title = "A4" + Environment.NewLine + "B4",
Status = 1,
DownloadProgress = "0"
});
_mainList.Add(new DownloadListDto()
{
Id = 5,
Title = "A5" + Environment.NewLine + "B5",
Status = 1,
DownloadProgress = "0"
}); _table = _mainList.ToDataTable();
this.uiDataGridView1.DataSource = _table; LoadingHelper.CloseForm();
uiDataGridView1.ClearSelection();
} private void uiDataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewRow row = uiDataGridView1.Rows[e.RowIndex]; if (uiDataGridView1.Columns[e.ColumnIndex].Name == "clTitle")
{
if (row.Cells["clStatus"].Value is int)
{
var intStatus = (int)row.Cells["clStatus"].Value;
if (intStatus == 1)
{
row.Cells["clOpDown"].Value = FileHelper.loadImageFromLocalPath(@"FileFolder/Icon/downLoad.png");
row.Cells["clOpDelete"].Value = FileHelper.loadImageFromLocalPath(@"FileFolder/Icon/delete1.png");
}
else if (intStatus == 2)
{
row.Cells["clOpDown"].Value = FileHelper.loadImageFromLocalPath(@"FileFolder/Icon/pause.png");
row.Cells["clOpDelete"].Value = FileHelper.loadImageFromLocalPath(@"FileFolder/Icon/delete1.png");
//row.Cells["clOpDelete"].Value = null;
}
else
{
// 创建一个1x1像素的透明图像
Bitmap transparentImage = new Bitmap(1, 1);
transparentImage.SetPixel(0, 0, Color.Transparent);
row.Cells["clOpDown"].Value = transparentImage;
row.Cells["clOpDelete"].Value = transparentImage;
}
} }
} private void uiDataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
//uiDataGridView1.ClearSelection();
} private async void uiDataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (uiDataGridView1.Columns[e.ColumnIndex] is DataGridViewImageColumn && e.RowIndex >= 0)
{
// 获取当前行的数据行
var currentRow = uiDataGridView1.Rows[e.RowIndex];
var _Id = (int)currentRow.Cells["clId"].Value;
if (uiDataGridView1.Columns[e.ColumnIndex].Name == "clOpDown")
{ //var currentData = _mainList.Find(x => x.Id == _Id);
var currentData = _table.AsEnumerable().FirstOrDefault(x => x.Field<int>("Id") == _Id);
if (currentData != null)
{
if (currentData["Status"].ToString() == "1")
{//1代表 未下载 currentData["Status"] = "2";//修改图标
uiDataGridView1.Refresh(); }
else
{//2代表 正在下载 _taskCondition = false;//终止执行任务
currentData["Status"] = "1";//修改图标
uiDataGridView1.Refresh(); }
//currentData.Status = 1;
//_taskCondition = false;
//uiDataGridView1.Refresh();
}
} if (uiDataGridView1.Columns[e.ColumnIndex].Name == "clOpDelete")
{ // 使用Linq查询匹配的行
var rowsToDelete = _table.AsEnumerable().FirstOrDefault(row => row.Field<int>("Id") == _Id);
_table.Rows.Remove(rowsToDelete);
}
}
}
public void DeleteMainData(int Id)
{
var currentData = _mainList.Find(x => x.Id == Id);
if (currentData != null)
{
_mainList.Remove(currentData);
uiDataGridView1.DataSource = _mainList;
uiDataGridView1.Refresh();
}
} private void uiDataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
uiDataGridView1.Visible = true;
_lbNotData.Visible = false;
DataGridView dataGridView = (DataGridView)sender;
if (dataGridView.Rows.Count == 0)
{
uiDataGridView1.Dock = DockStyle.None;
uiDataGridView1.Visible = false; _lbNotData.Visible = true;
}
} private void uiDataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
// 取消默认的错误处理行为
e.ThrowException = false; // 获取出错的单元格
DataGridViewCell errorCell = uiDataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]; // 获取出错的数据
object errorValue = uiDataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; // 自定义错误处理逻辑
MessageBox.Show("数据错误:" + e.Exception.Message); // 可以将出错的单元格的值重置为默认值
errorCell.Value = errorCell.DefaultNewRowValue;
}
}
}

结语

上面完整代码是.cs的代码。大家拷贝本地使用的时候需要在UI界面进行拖拉组件。本例子用的是winform SunnyUI 的框架 。框架文档在这里:文档预览 - Gitee.com

c# winfrom DataGridView 动态UI下载功能(内含GIF图) || 循环可变化的集合 数组 datatable 等的更多相关文章

  1. Struts2实现文件的上传与动态下载功能。

    本篇主要使用Struts2实现文件的上传与动态下载功能.出于安全考虑,所以,在硬盘上存储上传的文件的时候,统一都重新命名为随机字符串.用数据库存储真实文件名与随机文件名称之间的关联. 下面的是实体类 ...

  2. Android - 用Fragments实现动态UI - 使用Android Support Library

    Android Support Library提供了一个带有API库的JAR文件来让你可以在使用最新的Android API的同时也也已在早期版本的Android上运行.例如,Support Libr ...

  3. iNeedle日志下载功能问题

    问题: iNeedle系统本身包含日志下载功能,主要是将web服务器中的用户访问日志按照一定条件进行筛选并下载,提供管理者分析.但是这次的测试中发现iNeedle日志下载一直会卡住,web界面显示正在 ...

  4. 【ASP.NET Web API教程】2.3.5 用Knockout.js创建动态UI

    原文:[ASP.NET Web API教程]2.3.5 用Knockout.js创建动态UI 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容 ...

  5. 【Android Developers Training】 19. 序言:通过Fragments构建动态UI

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. GIF图保存下来不会动?用Folx的浏览器捕获下载功能试试!

    表情包大多是GIF格式的动图,有时候使用浏览器的另存为保存完发现并不能动态播放,怎么办呢?试试Folx提供的浏览器捕获下载功能,就能将各种格式的图片,包括GIF动图的下载链接捕获下来,供进一步下载使用 ...

  7. Safari 下用 "location.href = filePath" 实现下载功能的诡异 bug

    Safari 下的一些诡异 bug 我们已经领教一二,比如前文中说的 无痕浏览模式下使用 localStorage 的 API 就会报错.今天我们要讲的是利用 location.href = file ...

  8. location.href 实现点击下载功能

    如果页面上要实现一个点击下载的功能,传统做法是使用一个 a 标签,然后将该标签的 href 属性地址指向下载文件在服务端的地址(相对地址或者绝对地址),比如这样: 能这样实现是因为,在浏览器地址栏输入 ...

  9. php实现文件上传下载功能小结

    文件的上传与下载是项目中必不可少的模块,也是php最基础的模块之一,大多数php框架中都封装了关于上传和下载的功能,不过对于原生的上传下载还是需要了解一下的.基本思路是通过form表单post方式实现 ...

  10. JavaWeb学习记录(一)——response响应头之缓存设置与下载功能的实现

    一.HTTP中常用响应头 Location: http://www.it315.org/index.jsp Server:apache tomcat Content-Encoding: gzip Co ...

随机推荐

  1. Javscript数组的常用方法有哪些?

    数组基本操作可以归纳为 增.删.改.查,需要留意的是哪些方法会对原数组产生影响,哪些方法不会 下面对数组常用的操作方法做一个归纳 增 下面前三种是对原数组产生影响的增添方法,第四种则不会对原数组产生影 ...

  2. 力扣744(java&python)- 寻找比目标字母大的最小字母(简单)

    题目: 给你一个排序后的字符列表 letters ,列表中只包含小写英文字母.另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母. 在比较时,字母是依序循环出现的.举个例 ...

  3. 力扣560(java&python)-和为k的子数组(中等)

    题目: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 . 示例 1: 输入:nums = [1,1,1], k = 2输出:2示例 2: 输入:n ...

  4. 阿里云架构师梁旭:MES on 云盒,助力客户快速构建数字工厂

    简介: 四大优势:一站式交付.业务低延时.数据本地驻留.多工厂统一运维 2022年5月18日,在"云上数字工厂与中小企业数字化转型创新论坛"暨"鼎捷MES & 阿 ...

  5. 阿里云PolarDB开源数据库社区与 Tapdata 联合共建开放数据技术生态

    ​简介:近日,阿里云PolarDB开源数据库社区宣布将与 Tapdata 联合共建开放数据技术生态. 近日,阿里云PolarDB开源数据库社区宣布将与 Tapdata 联合共建开放数据技术生态.在此之 ...

  6. 从no-code到low-code:企业级hpaPaaS的未来

    简介: 本文将简单谈一谈基于 no-code > low-code > pro-code 渐进式思路的研发体系. 引子 宜搭负责人骁勇给我举过一个例子,我们小时候逢年过节穿的衣服,都是去裁 ...

  7. Java中的读写锁ReentrantReadWriteLock详解,存在一个小缺陷

    写在开头 最近是和java.util.concurrent.locks包下的同步类干上了,素有 并发根基 之称的concurrent包中全是精品,今天我们继续哈,今天学习的主题要由一个大厂常问的Jav ...

  8. SpringBoot中几种好用的代码生成器(基于Mybatis-plus生成entity、mapper、xml等)

    前言 熟悉Spring框架的同学一定都知道MVC开发模式吧,控制器(Controller).业务类(Service).持久层(Repository).数据库映射(Mapper).各种DO类构成了我们服 ...

  9. SpringBoot-EasyExcel导出数据(带图片)

    前言 EasyExcel 是阿里巴巴开源的一个Java操作Excel的技术,和EasyPoi一样是封装Poi的工具类. 但是不同的地方在于,在EasyExcel中解决了Poi技术读取大批量数据耗费内存 ...

  10. Nginx 常用的基础配置(web前端相关方面)

    文章出处:https://juejin.cn/post/7196859948554715195 基础配置 user root; worker_processes 1; events { worker_ ...