C # implement the WinForm DataGridView control to support overlapping data binding

Source: Internet
Author: User

C # implement the WinForm DataGridView control to support overlapping data binding
We all know that the WinForm DataGridView control supports data binding. It is easy to use. You only need to specify the DataSource attribute to the corresponding data source. However, the data source must support the IListSource type, instead of implementation, it can be either the IListSource type or the IList type, for example, the List type or the DataTable type. We will not List them here, the main functions I implemented today are described in the title: The WinForm DataGridView control supports overlapping data binding, or additional data functions. What does it mean? To put it bluntly, data can be bound multiple times. The standard binding method only supports single binding, that is, the original data is cleared every time the binding is performed, stack data binding adds each binding to the DataGridView control in an additional form (original data retained). This enables paging loading, however, all loaded data can be fully displayed. This type of application scenario is common on the C/S side and also on the B/S side (for example, loading more buttons Under the dynamic QQ space) the following two methods are available for attaching data: the first method is to obtain the attribute value through reflection and add data rows cyclically.

Private static void AppendDataToGrid (DataGridView grid, IList <object> source) {int rowCount = grid. rows. count; List <maid> rows = new List <maid> (); Type t = source [0]. getType (); int rowIndex = grid. rows. add (); var girdCells = grid. rows [rowIndex]. cells; // Common. showProcessing ("loading data. Please wait... ", Common. mainForm, (o) => // {foreach (object item in source) {var row = new maid (); foreach (maid 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 ());}

 

In each of the two methods, the data source is merged and then rebound.
Protected void AppendDataToGrid <T, TResult> (maid, IList <T> source, Func <T, TResult> orderBy) where T: class {// Stopwatch watch = new Stopwatch (); // watch. start (); if (maid. rows. count> 0) {IEnumerable <T> bindsource = null; Common. showProcessing ("loading data. Please wait... ", 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 the amount of code, the second method is relatively simple. The first method is more efficient than the second method, because it is very simple, first, the data processed each time is always the data on each page. Second, the data processed each time is a collection of the original data and existing data. As the data volume increases, loading slows down, you can also give it a try. If you have other better methods, you can also share them. To reflect object-oriented and reusability, I changed 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 dview grid, dynamic dataSource) {if (! (Grid is IAppendDataAble <DataGridView>) {throw new Exception ("The DataGridView control has not implemented IAppendDataAble <DataGridView>. This method cannot be used! ");} 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 able) {AppendDataToGrid (grid, dataSource as DataTable );}} /// <summary> // append data to the DataGridView (supports IList <T> data sources) /// </summary> /// <param name = "grid"> </param> /// <param name = "source"> </param> private static void appendDataToGrid (DataGridView grid, IList <object> source) {int rowCount = grid. rows. count; List <maid> rows = new List <maid> (); Type t = source [0]. getType (); int rowIndex = grid. rows. add (); var girdCells = grid. rows [rowIndex]. cells; // Common. showProcessing ("loading data. Please wait... ", Common. mainForm, (o) => // {foreach (object item in source) {var row = new maid (); foreach (maid 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 the DataGridView (DataTable data sources supported) /// </summary> /// <param name = "grid"> </param> /// <param name = "table"> </param> private static void appendDataToGrid (DataGridView grid, dataTable table) {int rowCount = grid. rows. count; List <maid> rows = new List <maid> (); int rowIndex = grid. rows. add (); var girdCells = grid. rows [rowIndex]. cells; // Common. showProcessing ("loading data. Please wait... ", Common. mainForm, (o) => // {foreach (DataRow r in table. rows) {var row = new maid (); foreach (maid 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 ());}}}

 

To avoid misuse of the extension method, that is, to avoid the impact of a normal dview that does not need to attach data, I define an interface to regulate it: IAppendDataAble <out TControl>, of course, this interface applies to all controls, and then adds an AppendData judgment during the extension method. If the IAppendDataAble interface is implemented, it indicates that the additional data function is required and subsequent processing is performed. Otherwise, an error is returned. I am here to expand based on the DataGridView. You can also extend it based on the DataGridView2 defined by me, which is more convenient. In addition, I have implemented separate processing for the two data source types to meet most of the requirements. The method comment out is the method used to display the mask layer. If you need it, check my blog post: How to Use the Winform application to implement the universal mask layer is as follows: 1. add the DataGridView control and change the DataGridView type to the DataGridView2 type. If you do not need to extend the control, you do not need to change the DataGridView control type. 2. Set the DataGridView column and set the DataPropertyName of the column 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 is of the DataGridView2 type // dataSource is the data dataGridView2Demo queried. appendData (dataSource). To improve the execution efficiency of the extension method and reduce the data source type judgment and conversion, we can also divide the extension method into two extension methods:
Public static class ControlExtension {// <summary> // attach data to the DataGridView (supports IList <T> data sources) /// </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 <maid> rows = new List <maid> (); Type t = typeof (T); int rowIndex = grid. rows. add (); var girdCells = grid. rows [rowIndex]. cells; Common. showProcessing ("loading data. Please wait... ", Common. mainForm, (o) =>{ foreach (object item in source) {var row = new maid (); foreach (maid 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 the DataGridView (DataTable data sources supported) /// </summary> /// <param name = "grid"> </param> /// <param name = "table"> </param> public static void appendData (this DataGridView grid, dataTable table) {int rowCount = grid. rows. count; List <maid> rows = new List <maid> (); int rowIndex = grid. rows. add (); var girdCells = grid. rows [rowIndex]. cells; Common. showProcessing ("loading data. Please wait... ", Common. mainForm, (o) =>{ foreach (DataRow r in table. rows) {var row = new maid (); foreach (maid 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 ());}}

 


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.