当前位置:网站首页>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
边栏推荐
- 7.2每日学习4
- 技术管理进阶——什么是管理者之体力、脑力、心力
- 【爬虫】wasm遇到的bug
- Lombok makes ⽤ @data and @builder's pit at the same time. Are you hit?
- [SWT component] content scrolledcomposite
- In the last process before the use of the risk control model, 80% of children's shoes are trampled here
- DDR4硬件原理图设计详解
- MySQL 巨坑:update 更新慎用影响行数做判断!!!
- 中非 钻石副石怎么镶嵌,才能既安全又好看?
- 基础篇——REST风格开发
猜你喜欢
Advanced technology management - what is the physical, mental and mental strength of managers
【爬虫】charles unknown错误
基于OpenHarmony的智能金属探测器
【Oracle】使用DataGrip连接Oracle数据库
【爬虫】wasm遇到的bug
Characteristics and electrical parameters of DDR4
Codeforces Round #804 (Div. 2)
数据库三大范式
Summary of thread and thread synchronization under window
How can China Africa diamond accessory stones be inlaid to be safe and beautiful?
随机推荐
[crawler] Charles unknown error
无密码身份验证如何保障用户隐私安全?
What about SSL certificate errors? Solutions to common SSL certificate errors in browsers
Intelligent metal detector based on openharmony
Go language learning notes - first acquaintance with go language
[LeetCode] Wildcard Matching 外卡匹配
Ziguang zhanrui's first 5g R17 IOT NTN satellite in the world has been measured on the Internet of things
龙蜥社区第九次运营委员会会议顺利召开
[TCP] TCP connection status JSON output on the server
MySQL giant pit: update updates should be judged with caution by affecting the number of rows!!!
2048游戏逻辑
go语言学习笔记-分析第一个程序
【Office】Excel中IF函数的8种用法
MySQL 巨坑:update 更新慎用影响行数做判断!!!
Zcmu--1390: queue problem (1)
R3live series learning (IV) r2live source code reading (2)
AutoCAD -- mask command, how to use CAD to locally enlarge drawings
COMSOL--建立几何模型---二维图形的建立
-26374 and -26377 errors during coneroller execution
OneForAll安装使用