当前位置:网站首页>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
边栏推荐
- 分类TAB商品流多目标排序模型的演进
- Unity Xlua MonoProxy Mono代理类
- Codeforces Round #804 (Div. 2)
- 7.2每日学习4
- MySQL giant pit: update updates should be judged with caution by affecting the number of rows!!!
- Pytorch training process was interrupted
- Crawler (9) - scrape framework (1) | scrape asynchronous web crawler framework
- [advertising system] incremental training & feature access / feature elimination
- 爬虫(9) - Scrapy框架(1) | Scrapy 异步网络爬虫框架
- Characteristics and electrical parameters of DDR4
猜你喜欢
【爬虫】charles unknown错误
龙蜥社区第九次运营委员会会议顺利召开
【爬虫】wasm遇到的bug
Intelligent metal detector based on openharmony
数据库三大范式
Evolution of multi-objective sorting model for classified tab commodity flow
Lombok makes ⽤ @data and @builder's pit at the same time. Are you hit?
COMSOL--三维随便画--扫掠
How to make full-color LED display more energy-saving and environmental protection
Codeforces Round #804 (Div. 2)
随机推荐
Deepfake tutorial
DDRx寻址原理
Solve the problem of slow access to foreign public static resources
力扣(LeetCode)185. 部门工资前三高的所有员工(2022.07.04)
The ninth Operation Committee meeting of dragon lizard community was successfully held
871. Minimum Number of Refueling Stops
Intelligent metal detector based on openharmony
How did the situation that NFT trading market mainly uses eth standard for trading come into being?
DDR4硬件原理图设计详解
【Oracle】使用DataGrip连接Oracle数据库
Cron expression (seven subexpressions)
How to make full-color LED display more energy-saving and environmental protection
无密码身份验证如何保障用户隐私安全?
Solve the grpc connection problem. Dial succeeds with transientfailure
Basics - rest style development
How does redis implement multiple zones?
Lombok 同时使⽤@Data和@Builder 的坑,你中招没?
Characteristics and electrical parameters of DDR4
Harbor镜像仓库搭建
[advertising system] parameter server distributed training