当前位置:网站首页>C # implements WinForm DataGridView control to support overlay data binding
C # implements WinForm DataGridView control to support overlay data binding
2022-07-05 11:28:00 【Full stack programmer webmaster】
We all know WinForm DataGridView Control support data binding , The method is simple to use , Just put the DataSource Attribute to the corresponding data source , But note that the data source must support IListSource type , What we are talking about here is support , Not implementation , Because he can realize IListSource The type of , It can also be realized IList The type of , for example :List type ,DataTable Type, etc , Here is not a list , Today, I mainly realize the functions described in the title : Realization WinForm DataGridView Control supports overlay data binding , Or additional data function , What does that mean ? To put it bluntly, it supports multiple binding of data , The standard binding method only supports single binding , That is, each binding will clear the original data , Superimposed data binding can realize that each binding is in the form of attachment ( Original data retention ) Add to DataGridView Control , This enables paging loading , However, all loaded data can be displayed completely , This application scenario is in C/S End is very common ,B/S There are also ( for example QQ Load more buttons under space dynamics )
Here are two ways to implement additional data :
The first way , Use reflection to get attribute values and add data rows circularly
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(" Loading data , Please wait a moment ...", 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());
}Every two ways , Merge data sources , Then rebind
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(" Loading data , Please wait a moment ...", 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());
}In terms of code quantity, the above two methods , The second is relatively simple , The first method is more efficient than the second method , The reason is simple , The first kind of data processed every time is always the data of every page , The second kind of data processed each time is the combination of original data and existing data , As the amount of data increases , The slower the loading , You can also try , Of course, if you have other better methods, you can also share .
In order to embody object-oriented and reusability , I change the above method into an extension method , The complete code is as follows :
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(" The DataGridView Control is not implemented IAppendDataAble<DataGridView>, Cannot use this method !");
}
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>
/// Attach data to DataGridView( Support IList<T> Data source of type )
/// </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(" Loading data , Please wait a moment ...", 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>
/// Attach data to DataGridView( Support DataTable Data source of type )
/// </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(" Loading data , Please wait a moment ...", 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());
}
}
}Explain the code a little , In order to avoid the abuse of extension methods , That is, ordinary without additional data DataGridView Impact , I define an interface to regulate it :IAppendDataAble<out TControl>, Of course, this interface applies to all controls , Then when extending the method AppendData Add judgment , If it's done IAppendDataAble Interface , It indicates that additional data function is required , Just do the following processing , Otherwise, the report will be wrong . I'm based here DataGridView To expand , You can also base on my definition DataGridView2 To expand , It's more convenient . in addition , I have implemented the above processing for two data source types , To meet most situations .
Method one of the methods commented out is the method I wrote to display the mask layer , If you need , You can check my blog :Winform The application implements a universal mask layer
How to use it is as follows :
1. add to DataGridView Control , And then DataGridView Change the type to DataGridView2 type , Of course, if you don't need extension constraints , Then there is no need to change DataGridView Control types .
2. Set up DataGridView Column , List the DataPropertyName Set to the name of the data field to be bound , This step is very important .
3. Then query the data and call the extension method :
//dataGridView2Demo by DataGridView2 type
//dataSource For the queried data
dataGridView2Demo.AppendData(dataSource);In order to improve the execution efficiency of the extension method , Reduce data source type judgment and conversion , We can also choose to directly divide the extension method into two extension methods , as follows :
public static class ControlExtension
{
/// <summary>
/// Attach data to DataGridView( Support IList<T> Data source of type )
/// </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(" Loading data , Please wait a moment ...", 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>
/// Attach data to DataGridView( Support DataTable Data source of type )
/// </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(" Loading data , Please wait a moment ...", 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());
}
}Use method unchanged , As for which one to use, it depends on your preferences !
Publisher : Full stack programmer stack length , Reprint please indicate the source :https://javaforall.cn/109478.html Link to the original text :https://javaforall.cn
边栏推荐
- [first release in the whole network] (tips for big tables) sometimes it takes only 1 minute for 2 hours of SQL operation
- Basic part - basic project analysis
- Ffmpeg calls avformat_ open_ Error -22 returned during input (invalid argument)
- 阻止浏览器后退操作
- 7.2每日学习4
- Spark Tuning (I): from HQL to code
- POJ 3176-Cow Bowling(DP||记忆化搜索)
- The art of communication III: Listening between people
- MFC pet store information management system
- Sklearn model sorting
猜你喜欢

中非 钻石副石怎么镶嵌,才能既安全又好看?

R3live series learning (IV) r2live source code reading (2)

Summary of thread and thread synchronization under window

Go language learning notes - analyze the first program

comsol--三维图形随便画----回转

Cdga | six principles that data governance has to adhere to

go语言学习笔记-分析第一个程序

DDR4的特性与电气参数
![[crawler] bugs encountered by wasm](/img/29/6782bda4c149b7b2b334238936e211.png)
[crawler] bugs encountered by wasm

Is it difficult to apply for a job after graduation? "Hundreds of days and tens of millions" online recruitment activities to solve your problems
随机推荐
数据库三大范式
COMSOL--建立几何模型---二维图形的建立
Three suggestions for purchasing small spacing LED display
Unity xlua monoproxy mono proxy class
C # to obtain the filtered or sorted data of the GridView table in devaexpress
7.2 daily study 4
如何将 DevSecOps 引入企业?
Basics - rest style development
Spark Tuning (I): from HQL to code
Modulenotfounderror: no module named 'scratch' ultimate solution
使用GBase 8c数据库过程中报错:80000305,Host ips belong to different cluster ,怎么解决?
【DNS】“Can‘t resolve host“ as non-root user, but works fine as root
SSL证书错误怎么办?浏览器常见SSL证书报错解决办法
Ffmpeg calls avformat_ open_ Error -22 returned during input (invalid argument)
An error is reported in the process of using gbase 8C database: 80000305, host IPS long to different cluster. How to solve it?
COMSOL -- 3D casual painting -- sweeping
管理多个Instagram帐户防关联小技巧大分享
Risc-v-qemu-virt in FreeRTOS_ Scheduling opportunity of GCC
How did the situation that NFT trading market mainly uses eth standard for trading come into being?
Dspic33ep clock initialization program