DevExpress使用教程:XtraGrid常見用法

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

XtraGrid與傳統的DataGridView同樣,支持多種類型做爲其數據源。下面例子是將DataTable, List和數組分別綁定到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;</t></person></person>

統計運算的功能

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

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

或者經過代碼設置,例如:ide

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

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

排序

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

或者經過代碼,例如:spa

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就能夠進行篩選。excel

該屬性經過代碼設置是

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 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值。

數據驗證

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

一、使用RepositoryItem.Validating事件

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

二、使用 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 name="e">
         private void btEdit_Click(object sender, EventArgs e)
         {
             Person p = (Person)gridView1.GetRow(gridView1.FocusedRowHandle);
         }
 
         /// <summary>
         /// 刪除
         /// </summary>
         /// <param name="sender">
         /// <param name="e">
         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 name="e">
         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方法。還 有更好的辦法還請高手們的指點。

出處:博客園武勝-阿偉

相關文章
相關標籤/搜索