DevExpress XtraGrid控件

下面彙總了DevExpress XtraGrid控件的各種常見用法,在此分享給大家:

DXperience Universal Suite下載

支持多種類型的數據集合作爲數據源

XtraGrid與傳統的DataGridView一樣,支持多種類型作爲其數據源。下面例子是將DataTable, List<T>和數組分別綁定到XtraGrid裏面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
     
//定義數據源
List<Person> peopleList=new List<Person>
{
    { ID = 1, FirstName = "Magnus", LastName = "Hedlund", Sex = true, Birth = new DateTime(1999, 9, 9), Chinese = 60, English = 80, Math = 79 },
    { ID = 2, FirstName = "Terry", LastName = "Adams", Sex = false, Birth = new DateTime(1999, 9, 9), Chinese = 60, English = 80, Math = 79 },
    { ID = 3, FirstName = "Charlotte", LastName = "Weiss", Sex = false, Birth = new DateTime() },
    { ID = 4, FirstName = "Arlene", LastName = "Huff", Sex = true, Birth = new DateTime(1999, 9, 9), Chinese = 60, English = 80, Math = 79 },
    { ID = 5, FirstName = "FirstName1", LastName = "LastName1", Sex = true, Birth = new DateTime(1999, 9, 9), Chinese=60, English=80, Math=79 },
   { ID = 6, FirstName = "FirstName2", LastName = "LastName2", Sex = true, Birth = new DateTime(1999, 9, 19), Chinese = 60, English = 80, Math = 79 },
   { ID = 7, FirstName = "FirstName3", LastName = "LastName3", Sex = true, Birth = new DateTime(1999, 9, 29) },
   { ID = 8, FirstName = "FirstName4", LastName = "LastName4", Sex = true, Birth = new DateTime(1999, 2, 9), Chinese = 60, English = 80, Math = 79 },
   { ID = 9, FirstName = "FirstName5", LastName = "LastName5", Sex = true, Birth = new DateTime(1999, 4, 9) }
};
//將list<T>綁定到grid中
gridControl1.DataSource = peopleList;
  
  
People[] peopleArray=peopleList.ToArray();
//將數組綁定到grid中
gridControl1.DataSource = peopleArray;
 
DataTable peopleTable=new DataTable();
  
peopleTable.Columns.Add("FirstName");
peopleTable.Columns.Add("LastName");
peopleTable.Columns.Add("Sex");
peopleTable.Columns.Add("Birth");
peopleTable.Columns.Add("Chinese");
peopleTable.Columns.Add("English");
peopleTable.Columns.Add("Math");
peopleTable.Columns.Add("ID");
  
foreach (Person pi in people)
{
    DataRow row = peopleTable.Rows.Add();
    row["FirstName"] = pi.FirstName;
    row["LastName"] = pi.LastName;
    row["Sex"] = pi.Sex;
    row["Birth"] = pi.Birth;
    row["Chinese"] = pi.Chinese;
    row["English"] = pi.English;
    row["Math"] = pi.Math;
    row["ID"]=pi.ID;
}
  
//將DataTable綁定到grid中
gridControl1.DataSource = peopleTable;

統計運算的功能

XtraGrid提供的統計運算的功能,包括求和,求平均值,最大值,最小值,行數,自定義統計。

做法是打開屬性編輯器,在Columns ——> Columns properties下的 SummaryItem的SummaryType選擇。

或者通過代碼設置,例如:

1
this.bandedGridColumn2.SummaryItem.SummaryType= DevExpress.Data.SummaryItemType.Average;

DevExpress.Data.SummaryItemType是一個枚舉,它的值有 Sum,Average,Max,Min,Count,Custom和None。

排序

只要該列的ColumnsOptions的AllowSort屬性不爲False就可以根據那一列的數據進行排序。(AllowSort屬性 在屬性編輯器的Columns的Columns Options選項卡。)設置Column properties下的SortOrder值。

或者通過代碼,例如:

1
2
3
this.bandedGridColumn2.OptionsColumn.AllowSort=  DevExpress.Utils.DefaultBoolean.Default| DevExpress.Utils.DefaultBoolean.True;
 
this.bandedGridColumn2.SortOrder= DevExpress.Data.ColumnSortOrder.Ascending

另外在程序運行時,單擊某列的列頭也可以對該列進行排序。

分組

1
2
3
4
5
GridView view = gridControl1.MainView as GridView;
[] sortInfo = {
        new GridColumnSortInfo(view.Columns["Chinese"], ColumnSortOrder.Ascending)
      };
view.SortInfo.(sortInfo, 2);

GridColumnSortInfo 數組存放的是分組的列的信息,調用ClearAndAddRange清除結果並進行分組。

篩選

只要該列的Filter Options選項卡的AllowFilter屬性不爲False就可以進行篩選。

該屬性通過代碼設置是

1
this.bandedGridColumn2.OptionsFilter.AllowFilter = false;

運行程序後,鼠標指針移動到列標題,單擊漏斗狀圖形經行篩選操作。

分頁欄

XtraGrid提供分頁欄。通過這個設置可以顯示出來。

1
gridControl1.UseEmbeddedNavigator = true;

如果要根據滾動條滾動實現翻頁功能的,那得依靠Scroll事件。它又沒像DataGridView那樣開放滾動條事件,不過裏面有一個事件可以替代Scroll事件,那就是TopRowChanged,例子如下:

1
2
3
4
5
6
7
8
private void gridView1_TopRowChanged(object sender, EventArgs e)
        {
 
            if (gridView1.IsRowVisible(gridView1.RowCount - 1) == RowVisibleState.Visible) //如果滾到了底端
            {
                people.AddRange(new Person[] { Person1, Person2, Person3, Person4, Person5 });
            }
        }

如果硬要獲取滾動條對象來設置,則可以用下面這段代碼獲取gridView的滾動條。

1
2
3
4
5
6
7
8
9
Type type = gridView1.GetType();
 
            FieldInfo fi = type.GetField("fViewInfo", BindingFlags.NonPublic | BindingFlags.Instance);
 
            GridViewInfo info = gridView1.GetViewInfo() as GridViewInfo;
 
            fi = type.GetField("scrollInfo", BindingFlags.NonPublic | BindingFlags.Instance);
 
            ScrollInfo scrollInfo = fi.GetValue(gridView1) as ScrollInfo;

父子表

當綁定的 數據源中的子項再存在集合時,XtraGrid會自動啓用子表。例如上面的在Person類裏多添加一個成員 List<Person> Friends{get;set;}表示那個人的朋友圈子,在任意一個實例中把Person實例添加進去,再啓動程序時,就會發現父子表的效果實現了。

若要對子表的進行設置,可以給MainView添加MasterRowExpanded事件,例如:

1
2
3
4
5
6
7
8
9
10
11
private void gridView1_MasterRowExpanded(object sender, CustomMasterRowEventArgs e)
        {
            //獲取子表
            AdvBandedGridView gv = (AdvBandedGridView)gridView1.GetDetailView(e.RowHandle, e.RelationIndex);
            //第一個參數是行號,第二個參數是父子表關聯索引
             
            if (gv != null)
            {
                //對子表設置
            }
        }

Get/Set 單元格的值

通過調用GetRowCellValue獲取單元格的值。

1
2
3
4
public override object GetRowCellValue(
   int rowHandle, 
   GridColumn column
);

rowHandle是行的索引,column列的對象。

通過調用SetRowCellValue設置單元格的值

1
2
3
4
5
public void SetRowCellValue(
   int rowHandle, 
   GridColumn column, 
   object _value
);

rowHandle是行的索引,column列的對象。_value是單元格新的值。

以peopleList爲例

1
2
int englishS=Convert.ToDouble(0,gridView1.Columns["English"])+60;
SetRowCellValue(0,gridView1.Columns["English"],englishS);

在XtraGrid有另一種方式,就是直接設置數據源的值。對於上面這個例子,直接找到grid裏第一行數據對應的Person對象,設置它的English值。

數據驗證

有兩種方法來實現基於單元格的驗證:

1、使用RepositoryItem.Validating事件

事件的"sender" 必須轉換爲BaseEdit類型,使用EditValue來獲取當前輸入的值並進行校驗,如果校驗不通過,把e.Cancel設置True。這種方法一般用來對內置控件的單元格進行數據驗證。

2、使用 GridView.ValidatingEditor 事件

事件的"sender"必須轉換爲GridView類型,當前列可以從GridView.FocusedColumn屬性獲得,值可以從e.Value獲取,如果校驗不通過,需要把e.Valid設置爲False。
這種方法一般用於對整個Grid內的文本框進行數據驗證

在設置完事件之後需要寫一個GridView.InvalidValueException 的事件委託,如

1
2
3
4
5
private void gridView1_InvalidValueException(object sender, DevExpress.XtraGrid.Views.Base.InvalidValueExceptionEventArgs e) {
  e.ThrowException = false;
  e.WindowText = "驗證通過";
  e.DisplayError = true;
}

表格數據與數據源的數據同步

XtraGrid與DataGridView在數據源方面不同的是,對grid裏的數據進行任何改動(增、刪、改)之後,原本的數據源也相應的改動。通過下面例子可以得出此結論,在窗體添加刪,改兩個按鈕並綁定下面相應的事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <summary>
        /// 更改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btEdit_Click(object sender, EventArgs e)
        {
            Person p = (Person)gridView1.GetRow(gridView1.FocusedRowHandle);
        }
 
        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btDelete_Click(object sender, EventArgs e)
        {if (gridView1.SelectedRowsCount != 0)
                gridView1.DeleteSelectedRows();
            MessageBox.Show(people.Count.ToString());
        }

只要對grid的數據經過改動之後,單擊相應的按鈕就可以查看數據源的信息。

數據導入導出

XtraGrid 支持Html、Xml、Txt、Xsl導出,對應的導出器是ExportHtmlProvider、ExportXmlProvider、 ExportTxtProvider、ExportXslProvider。都在命名空間DevExpress.XtraExport裏面。

這裏封裝了一個數據導出的方法,可以導出上述列舉的類型,只需要傳入相應類型的provider就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
private void ExportTo(IExportProvider provider)
        {
            Cursor currentCursor = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
 
            this.FindForm().Refresh();
            BaseExportLink link = gridView1.CreateExportLink(provider);
            (link as GridViewExportLink).ExpandAll = false;
            link.ExportTo(true);
            provider.Dispose();
 
            Cursor.Current = currentCursor;
        }

調用時只需要創建一個相應的provider。

1
2
IExportProvider provider = new ExportXlsProvider(FullFileName); //這裏可以是ExportHtmlProvider、ExportXmlProvider、ExportTxtProvider
ExportTo(provider);

導入數據只嘗試了導入Excel的導入,利用ODBC讀取Excel的數據到DataTable中,再把DataTable綁定到XtraGrid中。

這裏也是封裝了一個讀取Excel數據的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private DataSet GetDataFromExcelWithAppointSheetName(string Path)
        {
            String strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" +
                     "Data Source=" + Path + ";" +
                     "Extended Properties=Excel 8.0;";
            OleDbConnection conn = new OleDbConnection(strConn);
            conn.Open();
            //返回Excel的架構,包括各個sheet表的名稱,類型,創建時間和修改時間等 
            DataTable dtSheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" });
            //包含excel中表名的字符串數組
            string[] strTableNames = new string[dtSheetName.Rows.Count];
            for (int k = 0; k < dtSheetName.Rows.Count; k++)
            {
                strTableNames[k] = dtSheetName.Rows[k]["TABLE_NAME"].ToString();
            }
            OleDbDataAdapter da = null;
            DataSet ds = new DataSet();
            //從指定的表明查詢數據,可先把所有表明列出來供用戶選擇
            string strExcel = "select * from[" + strTableNames[0] + "]";
            da = new OleDbDataAdapter(strExcel, conn);
            da.Fill(ds);
 
            return ds;
        }

以這樣方式調用。

1
DataSet ds = GetDataFromExcelWithAppointSheetName(FullFileName);

設置條帶狀的列

在選擇視圖時,選擇BandedGridView和AdvBandedGridView都是支持設置條帶狀的列。在屬性編輯器的Bands處可以對條帶進行管理,直接拖動列標題可以設置該列屬於哪個條帶。通過Bands屬性可以對各個條帶進行管理。

編輯器

XtraGrid提供了多種編輯器。這些能夠在Grid/CardView/BandedView中使用。在屬性編輯器中的In-place Editor Repository可以對編輯器進行管理。在Columns的ColumnEdit中選擇該列使用哪個編輯器。

也可以通過代碼實現:

1
2
3
4
5
6
RepositoryItemComboBox repositoryItemComboBox_abc=new RepositoryItemComboBox();
            //
            // 對編輯器進行設置
            //
 
            this.gridColumn1.ColumnEdit = repositoryItemComboBox_abc;  //在需要的列裏使用定義好的編輯器

單元格編輯

這個效果發現只使用與gridView這種視圖,同樣通過上,下,左,右四個方向的導航鍵控制光標移動,按回車進入編輯狀態,按Esc鍵不保存更改內容,按回車保存更改內容。

1
2
3
this.gridView1.OptionsSelection.MultiSelect = true;
            this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CellSelect;
            this.gridView1.OptionsSelection.UseIndicatorForSelection = false;

列拖動

只 要是在列屬性裏把AllowMove設置了True(它的默認值本身是True),在程序運行時,用戶都可以拖動列標題來改變列的位置。該屬性可以通過屬 性編輯器設置,在Columns-->Columns Options選項卡下的AllowMove。也可以通過代碼設置,如:

1
gridView1.Columns[0].OptionsColumn.AllowMove = true;

XtraGrid滾輪翻頁

滾輪翻頁與傳動的翻頁更爲方便,經過本人一番探討與琢磨終於在XtraGrid的GridView中實現了鼠標滾輪翻頁。

我新建了一個組件繼承原本的GridControl,在組件中添加了一個ImageList,專門存放一些資源圖片。用於實現動態圖的效果。

添加一個自定義委託的參數與枚舉,委託參數用於傳遞分頁的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class PagingEventArgs : EventArgs
    {
        public int PageSize { get; set; }
        public int PageIndex { get; set; }
    }
 
    public enum LoadState
    {
        /// <summary>
        /// 就緒
        /// </summary>
        Ready,
 
        /// <summary>
        /// 正在讀取
        /// </summary>
        Loading,
 
        /// <summary>
        /// 讀取完成
        /// </summary>
        Finish
    }

在組件的類裏面添加以下字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <summary>
        /// 頁面大小
        /// </summary>
        private int _int_page_size=20;
 
        /// <summary>
        /// 當前頁索引
        /// </summary>
        private int _int_page_index=1;
 
        /// <summary>
        /// 總記錄數
        /// </summary>
        private int _int_record_count;
 
        /// <summary>
        /// 讀取狀態
        /// </summary>
        private LoadState _LodaState_state;

添加以下屬性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/// <summary>
        /// 總記錄數
        /// </summary>
        public int RecordCount
        {
            get
            {
                if (!IsPaging) return 0;
                return _int_record_count;
            }
            set
            {
                if (!IsPaging) return ;
                _int_record_count = value;
                //當設置了新的記錄總數,自動讀取第一頁的內容
                if(value>0)
                    gridView_TopRowChanged(this, new EventArgs());
 
           else
                          {
                                  while (this.MainView.DataRowCount > 0)
                                        GridView_main_view.DeleteRow(0);
                                  this.RefreshDataSource();
                          }
            }
        }
 
        /// <summary>
        /// 每次讀取的行數
        /// </summary>
        public int PageSize
        {
            get
            {
                if (!IsPaging) return 0;
                return _int_page_size;
            }
            set
            {
                if (!IsPaging) return ;
                _int_page_size = value;
            }
        }
 
        /// <summary>
        /// 總頁數
        /// </summary>
        private int PageCount
        {
            get
            {
                if (RecordCount % PageSize == 0)
                    return RecordCount / PageSize;
                return RecordCount / PageSize + 1;
            }
        }
 
        /// <summary>
        /// Grid
        /// </summary>
        private GridView _GridView_main_view
        {
            get { return (GridView)this.MainView; }
        }
 
        /// <summary>
        /// 是否啓用分頁
        /// </summary>
        public bool IsPaging { get; set; }

添加以下委託與事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
        /// 內部使用的委託
        /// </summary>
        private delegate void myDelegate();
 
        /// <summary>
        /// 滾動翻頁的委託
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ScrollingToPageEventHandler(object sender, PagingEventArgs e);
 
        /// <summary>
        /// 滾動翻頁的事件
        /// </summary>
        public event ScrollingToPageEventHandler OnScrollingToPage;

以下則是一些對控件的設置,按照各人喜好可以有所更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
        /// 設置分頁欄
        /// </summary>
        private void InitEmbeddedNavigator()
        {this.EmbeddedNavigator.CustomButtons.AddRange(new DevExpress.XtraEditors.NavigatorCustomButton[] {
            new DevExpress.XtraEditors.NavigatorCustomButton(-1, -1, true, false, "", null)});
            this.EmbeddedNavigator.TextStringFormat = "  當前 {1} 行數據  ";
            this.UseEmbeddedNavigator = true;
 
        }
 
        /// <summary>
        /// 設置gridView
        /// </summary>
        private void InitGridView()
        {
            _GridView_main_view.TopRowChanged += new EventHandler(gridView_TopRowChanged);
        }

爲控件的事件註冊以下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void gridControl_Load(object sender, EventArgs e)
        {
            if (IsPaging)
            {
                _LodaState_state = LoadState.Ready;
 
                InitEmbeddedNavigator();
                InitGridView();
            }
        }
 
        private void gridView_TopRowChanged(object sender, EventArgs e)
        {
 
            lock (this)
            {
                if ( _int_page_index > PageCount || _LodaState_state != LoadState.Ready) return;
            }
 
            //檢查是否到達底部
            if (_GridView_main_view.IsRowVisible(_GridView_main_view.RowCount - 1) == RowVisibleState.Visible||
                _int_page_index==1)
            {
 
                lock (this)//設置成開始讀取狀態
                {
                    _LodaState_state = LoadState.Loading;
                }
                Thread thread_load_data = new Thread(new ThreadStart(LoadData));
                Thread thread_change_text = new Thread(new ThreadStart(ChangeLoadingImage));
                thread_change_text.Start();
                thread_load_data.Start();
            }
        }

TopRowChanged事件在grid的首行改變了就會觸發,類似於滾動條的Scroll事件。這裏開了兩個線程,第一個線程用於讀取數據,第二個線程用於實現動態圖。兩個線程調用的方法都在下面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/// <summary>
        /// 讀取數據
        /// </summary>
        private void LoadData()
        {
            int top_row_index = 0;
            int focus_index = 0;
            lock (this)
            {
                top_row_index = _GridView_main_view.TopRowIndex;
                focus_index = _GridView_main_view.FocusedRowHandle;
 
                //執行事件
                if (OnScrollingToPage == null)
                    throw new Exception("OnScrollingToPage can not be null");
 
                PagingEventArgs e = new PagingEventArgs();
                e.PageIndex = this._int_page_index;
                e.PageSize = this._int_page_size;
                OnScrollingToPage(this,e);
                 
            }
 
            //刷新grid的數據
            if (this.Parent.InvokeRequired)
            {
                this.Parent.Invoke(new myDelegate(delegate
                {
                    _GridView_main_view.TopRowIndex = top_row_index;
                    _GridView_main_view.FocusedRowHandle = focus_index;
           _GridView_main_view.RefreshData();
 
                }));
 
            }
            lock (this)
            {
                _LodaState_state = LoadState.Finish;//設置成讀取完成狀態
            }
        }
 
        /// <summary>
        /// 更替圖片
        /// </summary>
        private void ChangeLoadingImage()
        {
 
            int image_index = 0;
 
            if (this.Parent.InvokeRequired)//顯示loading的gif
            {
                this.Parent.Invoke(new myDelegate(delegate
                {
                    this.EmbeddedNavigator.Buttons.CustomButtons[0].Visible = true;
                }));
            }
            while (true)//循環更替圖片實現動態圖效果
            {
                lock (this)
                {
                    if (_LodaState_state != LoadState.Loading)//判定數據是否完成
                        break;
                }
 
                Thread.Sleep(120);
 
                if (image_index == 3)
                    image_index = 0;
                else
                    image_index++;
                if (this.Parent.InvokeRequired)
                {
                    //輪流更換圖片實現gif動態圖
                    this.Parent.Invoke(new myDelegate(delegate
                    {
                        this.EmbeddedNavigator.Buttons.CustomButtons[0].ImageIndex = image_index;
                    }));
                }
            }
 
            if (this.Parent.InvokeRequired)//隱藏loading的gif
            {
                this.Parent.Invoke(new myDelegate(delegate
                {
                    this.EmbeddedNavigator.Buttons.CustomButtons[0].Visible = false;
                }));
            }
 
 
 
            lock (this)
            {
                _LodaState_state = 0;
                _int_page_index++;
            }
 
        }

不過這個代碼有點問題,當GridControl綁定的數據源有相同實例的子項時,隨着RefreshData方法的調用會不停觸發 TopRowChanged事件,確切的原因還沒搞清楚,解決這個問題就是要不去除數據源上相同的實例子項,要不就不調用RefreshData方法。還 有更好的辦法還請高手們的指點。

出處:博客園武勝-阿偉

發佈了22 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章