程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#實現WinForm DataGridView控件支持疊加數據綁定

C#實現WinForm DataGridView控件支持疊加數據綁定

編輯:C#入門知識

C#實現WinForm DataGridView控件支持疊加數據綁定


我們都知道WinForm DataGridView控件支持數據綁定,使用方法很簡單,只需將DataSource屬性指定到相應的數據源即可,但需注意數據源必須支持IListSource類型,這裡說的是支持,而不是實現,是因為他既可以是實現了IListSource的類型,也可以是實現了IList的類型,例如:List類型,DataTable類型等,這裡就不一一列舉了,今天我主要實現的功能如標題所描述的:實現WinForm DataGridView控件支持疊加數據綁定,或者說是附加數據功能,什麼意思呢?說白了就是支持數據的多次綁定,標准的綁定方法只支持單一綁定,即每次綁定均會清除原來的數據,而疊加數據綁定則可實現每次綁定均以附加的形式(原數據保留)添加到DataGridView控件中,這樣就實現了分頁加載,但可完整顯示已加載的所有數據,這種應用場景在C/S端很常見,B/S端上也有(例如QQ空間動態下面的加載更多按鈕)   以下是實現附加數據兩種方式:   第一種方式,采用反射獲取屬性值並循環添加數據行          
   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("正在加載數據,請稍候...", 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());

        }

 

  每二種方式,采用將數據源合並,然後重新綁定             
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("正在加載數據,請稍候...", 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());

        }

 

  以上兩種方法在代碼量來看,第二種比較簡單,第一種在執行效率上相對第二種方法要高,原因很簡單,第一種每次處理的數據永遠都是每頁的數據,而第二種每次處理的數據是原有數據與現有數據的合集,隨著數據量越多,加載也就越慢,大家也可以試一下,當然如果大家有其它更好的方法也可以分享一下。   為了體現面向對象以及可復用性,我將上述方法變為擴展方法,完整代碼如下:  
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("該DataGridView控件未實現IAppendDataAble<DataGridView>,無法使用該方法!");
            }

            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>
        /// 附加數據到DataGridView(支持IList<T>類型的數據源)
        /// </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("正在加載數據,請稍候...", 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>
        /// 附加數據到DataGridView(支持DataTable類型的數據源)
        /// </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("正在加載數據,請稍候...", 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());
        }

    }
}

 

  對代碼稍微說明一下,為了避免擴展方法被濫用,即不需要附加數據的普通DataGridView造成影響,我定義了一個接口來規范它:IAppendDataAble<out TControl>,當然這個接口適用於所有控件,然後在擴展方法時AppendData加判斷,如果實現了IAppendDataAble接口,則表明需要用到附加數據功能,就進行後面的處理,否則報錯。我這裡是基於DataGridView來擴展,大家也可以基於我定義的DataGridView2來擴展,這樣更方便。另外,我上面實現了針對兩種數據源類型進行了分別處理,以滿足大多數的情況。   方法種注釋掉的方法是我寫的顯示遮罩層的方法,如果大家需要,可以查看我的這篇博文:Winform應用程序實現通用遮罩層    使用方法如下:   1.添加DataGridView控件,然後將DataGridView類型更改為DataGridView2類型,當然如果大家不需要進行擴展約束,那就無需更改DataGridView控件類型。   2.設置DataGridView列,將列的DataPropertyName設置為需要綁定的數據字段名稱,這步很重要。   3.然後查詢數據並調用擴展方法:   //dataGridView2Demo為DataGridView2類型 //dataSource為查詢到的數據 dataGridView2Demo.AppendData(dataSource);  為了提高擴展方法的執行效率,降低數據源類型判斷及轉換,我們也可以選擇將擴展方法直接分為兩個擴展方法,如下:        
 public static class ControlExtension
    {
        /// <summary>
        /// 附加數據到DataGridView(支持IList<T>類型的數據源)
        /// </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("正在加載數據,請稍候...", 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>
        ///  附加數據到DataGridView(支持DataTable類型的數據源)
        /// </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("正在加載數據,請稍候...", 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());
        }

    }

 


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved