当前位置:网站首页>C#实现WinForm DataGridView控件支持叠加数据绑定
C#实现WinForm DataGridView控件支持叠加数据绑定
2022-07-05 11:22:00 【全栈程序员站长】
我们都知道WinForm DataGridView控件支持数据绑定,使用方法很简单,只需将DataSource属性指定到相应的数据源即可,但需注意数据源必须支持IListSource类型,这里说的是支持,而不是实现,是因为他既可以是实现了IListSource的类型,也可以是实现了IList的类型,例如:List类型,DataTable类型等,这里就不一一列举了,今天我主要实现的功能如标题所描述的:实现WinForm DataGridView控件支持叠加数据绑定,或者说是附加数据功能,什么意思呢?说白了就是支持数据的多次绑定,标准的绑定方法只支持单一绑定,即每次绑定均会清除原来的数据,而叠加数据绑定则可实现每次绑定均以附加的形式(原数据保留)添加到DataGridView控件中,这样就实现了分页加载,但可完整显示已加载的所有数据,这种应用场景在C/S端很常见,B/S端上也有(例如QQ空间动态下面的加载更多按钮)
以下是实现附加数据两种方式:
第一种方式,采用反射获取属性值并循环添加数据行
private static void AppendDataToGrid(DataGridView grid, IList<object> source)
{
int rowCount = grid.Rows.Count;
List<DataGridViewRow> rows = new List<DataGridViewRow>();
Type t = source[0].GetType();
int rowIndex = grid.Rows.Add();
var girdCells = grid.Rows[rowIndex].Cells;
//Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
//{
foreach (object item in source)
{
var row = new DataGridViewRow();
foreach (DataGridViewCell cell in girdCells)
{
var p = t.GetProperty(cell.OwningColumn.DataPropertyName);
object pValue = p.GetValue(item, null);
var newCell = (DataGridViewCell)cell.Clone();
newCell.Value = pValue;
row.Cells.Add(newCell);
}
rows.Add(row);
}
//});
grid.Rows.RemoveAt(rowIndex);
grid.Rows.AddRange(rows.ToArray());
}
每二种方式,采用将数据源合并,然后重新绑定
protected void AppendDataToGrid<T,TResult>(DataGridView dataGridBase, IList<T> source,Func<T,TResult> orderBy) where T : class
{
//Stopwatch watch = new Stopwatch();
//watch.Start();
if (dataGridBase.Rows.Count > 0)
{
IEnumerable<T> bindsource = null;
Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
{
var oldSource = (IList<T>)dataGridBase.DataSource;
bindsource = source.Concat(oldSource).OrderBy(orderBy).ToList();
});
dataGridBase.DataSource = bindsource;
}
else
{
dataGridBase.DataSource = source;
}
//watch.Stop();
//MessageBox.Show(watch.ElapsedMilliseconds.ToString());
}
以上两种方法在代码量来看,第二种比较简单,第一种在执行效率上相对第二种方法要高,原因很简单,第一种每次处理的数据永远都是每页的数据,而第二种每次处理的数据是原有数据与现有数据的合集,随着数据量越多,加载也就越慢,大家也可以试一下,当然如果大家有其它更好的方法也可以分享一下。
为了体现面向对象以及可复用性,我将上述方法变为扩展方法,完整代码如下:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data;
namespace Zwj.Demo
{
public interface IAppendDataAble<out TControl> where TControl : Control
{
}
public class DataGridView2 : DataGridView, IAppendDataAble<DataGridView>
{
}
public static class AppendDataAbleControlExtension
{
public static void AppendData(this DataGridView grid, dynamic dataSource)
{
if (!(grid is IAppendDataAble<DataGridView>))
{
throw new Exception("该DataGridView控件未实现IAppendDataAble<DataGridView>,无法使用该方法!");
}
if (dataSource.GetType().IsValueType || dataSource == null)
{
grid.DataSource = null;
return;
}
Type interfaceType=dataSource.GetType().GetInterface("System.Collections.IList", true);
if (interfaceType!=null)
{
List<object> list = new List<object>(); list.AddRange(dataSource); AppendDataToGrid(grid, list);
}
else if (dataSource is DataTable)
{
AppendDataToGrid(grid, dataSource as DataTable);
}
}
/// <summary>
/// 附加数据到DataGridView(支持IList<T>类型的数据源)
/// </summary>
/// <param name="grid"></param>
/// <param name="source"></param>
private static void AppendDataToGrid(DataGridView grid, IList<object> source)
{
int rowCount = grid.Rows.Count;
List<DataGridViewRow> rows = new List<DataGridViewRow>();
Type t = source[0].GetType();
int rowIndex = grid.Rows.Add();
var girdCells = grid.Rows[rowIndex].Cells;
//Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
//{
foreach (object item in source)
{
var row = new DataGridViewRow();
foreach (DataGridViewCell cell in girdCells)
{
var p = t.GetProperty(cell.OwningColumn.DataPropertyName);
object pValue = p.GetValue(item, null);
var newCell = (DataGridViewCell)cell.Clone();
newCell.Value = pValue;
row.Cells.Add(newCell);
}
rows.Add(row);
}
//});
grid.Rows.RemoveAt(rowIndex);
grid.Rows.AddRange(rows.ToArray());
}
/// <summary>
/// 附加数据到DataGridView(支持DataTable类型的数据源)
/// </summary>
/// <param name="grid"></param>
/// <param name="table"></param>
private static void AppendDataToGrid(DataGridView grid, DataTable table)
{
int rowCount = grid.Rows.Count;
List<DataGridViewRow> rows = new List<DataGridViewRow>();
int rowIndex = grid.Rows.Add();
var girdCells = grid.Rows[rowIndex].Cells;
//Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
//{
foreach (DataRow r in table.Rows)
{
var row = new DataGridViewRow();
foreach (DataGridViewCell cell in girdCells)
{
object pValue = r[cell.OwningColumn.DataPropertyName];
var newCell = (DataGridViewCell)cell.Clone();
newCell.Value = pValue;
row.Cells.Add(newCell);
}
rows.Add(row);
}
//});
grid.Rows.RemoveAt(rowIndex);
grid.Rows.AddRange(rows.ToArray());
}
}
}
对代码稍微说明一下,为了避免扩展方法被滥用,即不需要附加数据的普通DataGridView造成影响,我定义了一个接口来规范它:IAppendDataAble<out TControl>,当然这个接口适用于所有控件,然后在扩展方法时AppendData加判断,如果实现了IAppendDataAble接口,则表明需要用到附加数据功能,就进行后面的处理,否则报错。我这里是基于DataGridView来扩展,大家也可以基于我定义的DataGridView2来扩展,这样更方便。另外,我上面实现了针对两种数据源类型进行了分别处理,以满足大多数的情况。
方法种注释掉的方法是我写的显示遮罩层的方法,如果大家需要,可以查看我的这篇博文:Winform应用程序实现通用遮罩层
使用方法如下:
1.添加DataGridView控件,然后将DataGridView类型更改为DataGridView2类型,当然如果大家不需要进行扩展约束,那就无需更改DataGridView控件类型。
2.设置DataGridView列,将列的DataPropertyName设置为需要绑定的数据字段名称,这步很重要。
3.然后查询数据并调用扩展方法:
//dataGridView2Demo为DataGridView2类型
//dataSource为查询到的数据
dataGridView2Demo.AppendData(dataSource);
为了提高扩展方法的执行效率,降低数据源类型判断及转换,我们也可以选择将扩展方法直接分为两个扩展方法,如下:
public static class ControlExtension
{
/// <summary>
/// 附加数据到DataGridView(支持IList<T>类型的数据源)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="grid"></param>
/// <param name="source"></param>
public static void AppendData<T>(this DataGridView grid, IList<T> source) where T : class
{
int rowCount = grid.Rows.Count;
List<DataGridViewRow> rows = new List<DataGridViewRow>();
Type t = typeof(T);
int rowIndex = grid.Rows.Add();
var girdCells = grid.Rows[rowIndex].Cells;
Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
{
foreach (object item in source)
{
var row = new DataGridViewRow();
foreach (DataGridViewCell cell in girdCells)
{
var p = t.GetProperty(cell.OwningColumn.DataPropertyName);
object pValue = p.GetValue(item, null);
var newCell = (DataGridViewCell)cell.Clone();
newCell.Value = pValue;
row.Cells.Add(newCell);
}
rows.Add(row);
}
});
grid.Rows.RemoveAt(rowIndex);
grid.Rows.AddRange(rows.ToArray());
}
/// <summary>
/// 附加数据到DataGridView(支持DataTable类型的数据源)
/// </summary>
/// <param name="grid"></param>
/// <param name="table"></param>
public static void AppendData(this DataGridView grid, DataTable table)
{
int rowCount = grid.Rows.Count;
List<DataGridViewRow> rows = new List<DataGridViewRow>();
int rowIndex = grid.Rows.Add();
var girdCells = grid.Rows[rowIndex].Cells;
Common.ShowProcessing("正在加载数据,请稍候...", Common.MainForm, (o) =>
{
foreach (DataRow r in table.Rows)
{
var row = new DataGridViewRow();
foreach (DataGridViewCell cell in girdCells)
{
object pValue = r[cell.OwningColumn.DataPropertyName];
var newCell = (DataGridViewCell)cell.Clone();
newCell.Value = pValue;
row.Cells.Add(newCell);
}
rows.Add(row);
}
});
grid.Rows.RemoveAt(rowIndex);
grid.Rows.AddRange(rows.ToArray());
}
}
使用方法不变,至于用哪一种根据大家的喜好!
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/109478.html原文链接:https://javaforall.cn
边栏推荐
- 如何通俗理解超级浏览器?可以用于哪些场景?有哪些品牌?
- COMSOL--三维随便画--扫掠
- About the use of Vray 5.2 (self research notes) (II)
- Basics - rest style development
- Basic part - basic project analysis
- 9、 Disk management
- Some understandings of heterogeneous graphs in DGL and the usage of heterogeneous graph convolution heterographconv
- 华为设备配置信道切换业务不中断
- DDoS attack principle, the phenomenon of being attacked by DDoS
- 居家办公那些事|社区征文
猜你喜欢
随机推荐
IPv6与IPv4的区别 网信办等三部推进IPv6规模部署
How can edge computing be combined with the Internet of things?
Basic part - basic project analysis
Three suggestions for purchasing small spacing LED display
CDGA|数据治理不得不坚持的六个原则
comsol--三维图形随便画----回转
Beego cross domain problem solution - successful trial
Huawei equipment configures channel switching services without interruption
Operators
2022 mobile crane driver examination question bank and simulation examination
pytorch训练进程被中断了
无密码身份验证如何保障用户隐私安全?
Intelligent metal detector based on openharmony
Solve the problem of slow access to foreign public static resources
[there may be no default font]warning: imagettfbbox() [function.imagettfbbox]: invalid font filename
2022 Pengcheng cup Web
Three paradigms of database
【爬虫】charles unknown错误
Web Security
The art of communication III: Listening between people