开发者论坛

 找回密码
 注册 (请使用非IE浏览器)
查看: 2310|回复: 1

XtraGrid常见用法(二)

[复制链接]

0

精华

8

贡献

1768

赞扬

特约版主

帖子
583
软币
4524
在线时间
275 小时
注册时间
2019-2-21
发表于 2019-3-26 11:51:02 | 显示全部楼层 |阅读模式
本帖接着为大家汇总DevExpress XtraGrid控件的各种常见用法,在此分享给大家:


DevExpress Universal Suite下载


数据验证

有两种方法来实现基于单元格的验证:

1、使用RepositoryItem.Validating事件

事件的"sender" 必须转换为BaseEdit类型,使用EditValue来获取当前输入的值并进行校验,如果校验不通过,把e.Cancel设置True。这种方法一般用来对内置控件的单元格进行数据验证。

2、使用 GridView.ValidatingEditor 事件

事件的"sender"必须转换为GridView类型,当前列可以从GridView.FocusedColumn属性获得,值可以从e.Value获取,如果校验不通过,需要把e.Valid设置为False。
这种方法一般用于对整个Grid内的文本框进行数据验证

在设置完事件之后需要写一个GridView.InvalidValueException 的事件委托,如

[C#] 纯文本查看 复制代码
private void gridView1_InvalidValueException(object sender, DevExpress.XtraGrid.Views.Base.InvalidValueExceptionEventArgs e) {
  e.ThrowException = false;
  e.WindowText = "验证通过";
  e.DisplayError = true;
}

表格数据与数据源的数据同步

XtraGrid与DataGridView在数据源方面不同的是,对grid里的数据进行任何改动(增、删、改)之后,原本的数据源也相应的改动。通过下面例子可以得出此结论,在窗体添加删,改两个按钮并绑定下面相应的事件。

[C#] 纯文本查看 复制代码
/// <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就可以了。

[C#] 纯文本查看 复制代码
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。

[C#] 纯文本查看 复制代码
IExportProvider provider = new ExportXlsProvider(FullFileName); //这里可以是ExportHtmlProvider、ExportXmlProvider、ExportTxtProvider
ExportTo(provider);

导入数据只尝试了导入Excel的导入,利用ODBC读取Excel的数据到DataTable中,再把DataTable绑定到XtraGrid中。

这里也是封装了一个读取Excel数据的方法。

[C#] 纯文本查看 复制代码
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;
        }

以这样方式调用。

[C#] 纯文本查看 复制代码
DataSet ds = GetDataFromExcelWithAppointSheetName(FullFileName);

设置条带状的列

在选择视图时,选择BandedGridView和AdvBandedGridView都是支持设置条带状的列。在属性编辑器的Bands处可以对条带进行管理,直接拖动列标题可以设置该列属于哪个条带。通过Bands属性可以对各个条带进行管理。

编辑器

XtraGrid提供了多种编辑器。这些能够在Grid/CardView/BandedView中使用。在属性编辑器中的In-place Editor Repository可以对编辑器进行管理。在Columns的ColumnEdit中选择该列使用哪个编辑器。

也可以通过代码实现:

[C#] 纯文本查看 复制代码
RepositoryItemComboBox repositoryItemComboBox_abc=new RepositoryItemComboBox();
            //
            // 对编辑器进行设置
            //
 
            this.gridColumn1.ColumnEdit = repositoryItemComboBox_abc;  //在需要的列里使用定义好的编辑器

单元格编辑

这个效果发现只使用与gridView这种视图,同样通过上,下,左,右四个方向的导航键控制光标移动,按回车进入编辑状态,按Esc键不保存更改内容,按回车保存更改内容。

[C#] 纯文本查看 复制代码
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。也可以通过代码设置,如:

[C#] 纯文本查看 复制代码
gridView1.Columns[0].OptionsColumn.AllowMove = true;

XtraGrid滚轮翻页

滚轮翻页与传动的翻页更为方便,经过本人一番探讨与琢磨终于在XtraGrid的GridView中实现了鼠标滚轮翻页。

我新建了一个组件继承原本的GridControl,在组件中添加了一个ImageList,专门存放一些资源图片。用于实现动态图的效果。

添加一个自定义委托的参数与枚举,委托参数用于传递分页的信息。

[C#] 纯文本查看 复制代码
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
    }

在组件的类里面添加以下字段

[C#] 纯文本查看 复制代码
/// <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;

添加以下属性

[C#] 纯文本查看 复制代码
/// <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; }

添加以下委托与事件

[C#] 纯文本查看 复制代码
/// <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;

以下则是一些对控件的设置,按照各人喜好可以有所更改。

[C#] 纯文本查看 复制代码
/// <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);
        }

为控件的事件注册以下方法

[C#] 纯文本查看 复制代码
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事件。这里开了两个线程,第一个线程用于读取数据,第二个线程用于实现动态图。两个线程调用的方法都在下面。

[C#] 纯文本查看 复制代码
/// <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方法。还 有更好的办法还请高手们的指点。

出处:博客园武胜-阿伟


评分

参与人数 1赞扬 +1 收起 理由
kevenme + 1 感谢分享

查看全部评分

回复

使用道具 举报

Archiver|手机版|小黑屋|开发者网 ( 苏ICP备08004430号-2 )
版权所有:南京韵文教育信息咨询有限公司

GMT+8, 2024-4-25 14:49

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表