当前位置:网站首页>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

原网站

版权声明
本文为[Full stack programmer webmaster]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207051121312114.html