① 定时器的使用:把CreateTimer()放到用户控件的构造函数中,定时进行相应的操作,这里是检查是否有邮件的IsUnread属性是否变化了。 Timer messageReadTimer; void CreateTimer() { messageReadTimer = new Timer(); messageReadTimer.Interval = 3000; messageReadTimer.Tick += new EventHandler(messageReadTimer_Tick); } void messageReadTimer_Tick(object sender, EventArgs e) { if(CurrentMessage != null && CurrentMessage.IsUnread) { RaiseReadMessagesChanged(gridView1.FocusedRowHandle); messageReadTimer.Stop(); } } void RaiseReadMessagesChanged(int rowHandle) { Message current = gridView1.GetRow(rowHandle) as Message; if(current == null) return; current.ToggleRead();//切换是否已读状态,可定义在实体类中 gridView1.LayoutChanged(); OwnerForm.ReadMessagesChanged();//OwnerForm是指当前控件所在的主窗体,控件内发生的事件可能会引起主窗体内的一些变化,可以这样调用 gridView1.MakeRowVisible(gridView1.FocusedRowHandle); } OwnerForm 可以这样定义 : internal frmMain OwnerForm { get { return this.FindForm() as frmMain; } } ,因为其它用户控件也有可能此属性,所以最好定义一个父用户控件,把OwnerForm属性放到这个父用户控件中,让所有的用户控件都从这个父用户控件继承,这样所有的用户控件都可以使用这个属性了,其他类似属性同例。父用户控件的定义: public class BaseModule : BaseControl { internal frmMain OwnerForm { get { return this.FindForm() as frmMain; } } } ② 获取GridControl中的FindControl控件,可以把它定义成一属性,方便下次使用 FindControl FindControl { get { foreach(Control ctrl in gridControl1.Controls) { FindControl ret = ctrl as FindControl; if(ret != null) return ret; } return null; } } ③ 选中GridView中的一行,或者一组,要在窗口中其他位置(一用户控件)显示这条数据或者一组数据的信息,可以用如下操作完成: //这一方法可以在gridView1_FocusedRowChanged、gridView1_ColumnFilterChanged等触发GridView中焦点行改变的情况下使用 void UpdateCurrentMessage() { if(lockUpdateCurrentMessage) return;//有时候可能有这样一开关,不要进行这样的操作 if(gridView1.FocusedRowHandle >= 0)//如果FocusedRowHandle >= 0,说明选中了一条数据 CurrentMessage = gridView1.GetFocusedRow() as Message;//给CurrentMessage赋值时,已进行相应的操作,参考下面CurrentMessage的定义 else { List<Message> rows = new List<Message>(); GridHelper.GetChildDataRowHandles(gridView1, gridView1.FocusedRowHandle, rows);//这里是获取分组下的所有对象,并把对象加入到集合rows中,方法定义见 ④ ucMailViewer1.ShowMessagesInfo(rows); CurrentMessage = null;//因为是选择了一组对象,这里把当前所选对象设null messageReadTimer.Stop(); } RaiseEnableMail(gridView1.FocusedRowHandle >= 0); RaiseEnableDelete(EnableDelete); } Message currentMessage; Message CurrentMessage { get { return currentMessage; } set { if(currentMessage == value) return; currentMessage = value; ucMailViewer1.ShowMessage(CurrentMessage); messageReadTimer.Stop(); if(CurrentMessage != null && CurrentMessage.IsUnread) messageReadTimer.Start(); } } ④ GridHelper类的用法: public class GridHelper { //具体用法见 ③ public static void GetChildDataRowHandles(GridView view, int rowHandle, List<Message> list) { for(int i = 0; i < view.GetChildRowCount(rowHandle); i++) { int row = view.GetChildRowHandle(rowHandle, i); if(row >= 0) list.Add(view.GetRow(row) as Message); else GetChildDataRowHandles(view, row, list); } } //设置GridControl中FindControl的“查找”与“清除”图标 public static void SetFindControlImages(GridControl grid) { FindControl fControl = null; foreach(Control ctrl in grid.Controls) {//循环遍历,先判断GridControl中是否有FindControl控件 fControl = ctrl as FindControl; if(fControl != null) break; } if(fControl != null) { fControl.FindButton.Image = global::DevExpress.MailClient.Win.Properties.Resources.Search; fControl.ClearButton.Image = global::DevExpress.MailClient.Win.Properties.Resources.Delete_16x16; fControl.CalcButtonsBestFit(); } } //设置GridView的焦点定位到obj所在的那一行,如果不存在这一行,或者焦点本来就在这一行,焦点保持不变 public static void GridViewFocusObject(ColumnView cView, object obj) { if(obj == null) return; int oldFocusedRowHandle = cView.FocusedRowHandle; for(int i = 0; i < cView.DataRowCount; ++i) { object rowObj = cView.GetRow(i) as object; if(rowObj == null) continue; if(ReferenceEquals(obj, rowObj)) {//判断两实例是否相同 if(i == oldFocusedRowHandle)//如果焦点本来就在obj所在的那一行,不进行焦点切换操作 cView.FocusedRowHandle = GridControl.InvalidRowHandle;//属性InvalidRowHandle,无效Handle,试图获得一个特定的行失败 cView.FocusedRowHandle = i; break; } } } } ⑤ 键盘操作gridView1要进行的操作: private void gridView1_KeyDown(object sender, KeyEventArgs e) { if(e.KeyData == Keys.Enter) EditMessage(gridView1.FocusedRowHandle); } ⑥ 鼠标点击gridView1中的单元格进行的多种操作: private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) { if(e.Column == gcRead && e.Button == MouseButtons.Left)//单击某一特定单元格进行的操作 RaiseReadMessagesChanged(e.RowHandle); if(e.Column.FieldName == "Priority" && e.Button == MouseButtons.Left)//判断单元格是否在某一列,有多种方法:e.Column==列name,或者e.Column.FieldName==列绑定字段名,或者其他 PriorityMenu.ShowPopup(gridControl1.PointToScreen(e.Location)); //单击单元格,在鼠标点击位置弹出自定义的快捷菜单,一般用于修改状态,Menu定义见 ⑧ if(e.Button == MouseButtons.Right) ShowMessageMenu(gridControl1.PointToScreen(e.Location)); if(e.Button == MouseButtons.Left && e.Clicks == 2) //双击打开对象编辑窗口,具体方法见 ⑦ EditMessage(e.RowHandle); } ⑦ 打开编辑窗口,进行新增或者编辑操作: //默认是编辑操作,其实可以加一个boo型参数allowEdit来决定是查看和编辑操作,根据需求来变吧 void EditMessage(int rowHandle) { if(rowHandle < 0) return; Message message = gridView1.GetRow(rowHandle) as Message; if(message != null) EditMessage(message, false, gcFrom.Caption); } //新增 void CreateNewMailMessage() { Message message = new Message(); message.MailType = MailType.Draft; EditMessage(message, true, null); } //用参数newMessage来决定是新增还是编辑 void EditMessage(Message message, bool newMessage, string caption) { Cursor.Current = Cursors.WaitCursor;//打开新窗口的过程中,鼠标变成等待状态 frmEditMail form = new frmEditMail(message, newMessage, caption); form.Load += OnEditMailFormLoad; form.FormClosed += OnEditMailFormClosed; form.Location = new Point(OwnerForm.Left + (OwnerForm.Width - form.Width) / 2, OwnerForm.Top + (OwnerForm.Height - form.Height) / 2);//居中显示 form.Show(); Cursor.Current = Cursors.Default; } ⑧ 生成图片类,图片可以自适应大小 public class ImageCreator { public static Image CreateImage(Image srcImage, int maxWidth, int maxHeight) { if (srcImage == null) return null; Size size = GetPhotoSize(srcImage, maxWidth, maxHeight); Image ret = new Bitmap(size.Width, size.Height); using (Graphics gr = Graphics.FromImage(ret)) { gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; gr.DrawImage(srcImage, new Rectangle(0, 0, size.Width, size.Height)); } return ret; } static Size GetPhotoSize(Image image, int maxWidth, int maxHeight) { int width = Math.Min(maxWidth, image.Width), height = width * image.Height / image.Width; if (height > maxHeight) { height = maxHeight; width = height * image.Width / image.Height; } return new Size(width, height); } public static Rectangle GetZoomDestRectangle(Rectangle r, Image img) { float horzRatio = Math.Min((float)r.Width / img.Width, 1); float vertRatio = Math.Min((float)r.Height / img.Height, 1); float zoomRatio = Math.Min(horzRatio, vertRatio); return new Rectangle( r.Left + (int)(r.Width - img.Width * zoomRatio) / 2, r.Top + (int)(r.Height - img.Height * zoomRatio) / 2, (int)(img.Width * zoomRatio), (int)(img.Height * zoomRatio)); } } ⑨在GridView呈现前,动态改变分组或者row或者cell的样式:(执行顺序从上到下,遇见分组就执行分组的) private void gridView1_CustomDrawGroupRow(object sender, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs e) { GridGroupRowInfo info = e.Info as GridGroupRowInfo; if(info == null) return; info.GroupText = info.GroupText.Replace("1 items", "1 item");//修改分组中显示的文本信息 } private void gridView1_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e) { if(e.Column == gcSubject) { Message message = gridView1.GetRow(e.RowHandle) as Message; if(message != null) e.DisplayText = message.SubjectDisplayText;//修改单元格的的显示文本 } } ⑩ SplitContainerControl控件设置Panel的显示隐藏有下面两种方式:第一种把Panel2彻底隐藏,无法恢复;第二种是把Panel2缩了起来,可以点开 splitContainerControl1.PanelVisibility = SplitPanelVisibility.Panel1; splitContainerControl1.Collapsed = true; 11、 时间过滤菜单类 public class DateFilterMenu : PopupMenu { GridView view; FilterCriteriaManager filterManager; public DateFilterMenu(BarManager manager, GridView view, FilterCriteriaManager filterManager) : base(manager) { this.view = view; this.filterManager = filterManager; CreateBarItem(Properties.Resources.IsToday, "IsOutlookIntervalToday([Date])"); CreateBarItem(Properties.Resources.IsYesterday, "IsOutlookIntervalYesterday([Date])"); CreateBarItem(Properties.Resources.IsEarlierThisWeek, "IsOutlookIntervalEarlierThisWeek([Date])"); CreateBarItem(Properties.Resources.IsLastWeek, "IsOutlookIntervalLastWeek([Date])"); CreateBarItem(Properties.Resources.IsEarlierThisMonth, "IsOutlookIntervalEarlierThisMonth([Date])"); CreateBarItem(Properties.Resources.IsEarlierThisYear, "IsOutlookIntervalEarlierThisYear([Date])"); } void CreateBarItem(string caption, string filterString) { BarButtonItem item = new BarButtonItem(this.Manager, caption); item.Tag = filterString; item.CloseSubMenuOnClick = false; ItemLinks.Add(item); filterManager.AddBarItem(item, view.Columns["Date"], filterString); } } 12、 键盘控制窗口的一些用法 //void frmEditMail_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { // if (e.KeyCode == Keys.Escape) { // if (QueryClose() != DialogResult.Cancel) // Close(); // } //} void richEditControl_KeyDown(object sender, KeyEventArgs e) { if ((e.Modifiers & Keys.Control) != 0 && e.KeyCode == Keys.S) { ApplyChanges(); e.Handled = true; } } protected internal override void SendKeyDown(KeyEventArgs e) { base.SendKeyDown(e); if (e.KeyData == (Keys.E | Keys.Control)) { if (FindControl != null) { FindControl.FindEdit.Focus(); } } } 13、 窗体调用用户控件中事件: 在用户控件中定义委托(如果事件中没有参数,用EventHandler即可,不用自己再定义)和事件, 用户控件中相关代码: public event EventHandler CheckedChanged; this.ceAlphabetical.CheckedChanged += new System.EventHandler(this.ce_CheckedChanged);//用户控件中事件中方法的绑定 private void ce_CheckedChanged(object sender, EventArgs e) { CheckEdit ce = sender as CheckEdit; if(ce.Checked && CheckedChanged != null) { SetItemCheck(gallery.Gallery.GetAllItems()); CheckedChanged(sender, EventArgs.Empty); } } 窗体中相关代码: this.ucContacts1.CheckedChanged += new System.EventHandler(this.ucContacts1_CheckedChanged); private void ucContacts1_CheckedChanged(object sender, EventArgs e) { modulesNavigator.CurrentModule.ButtonClick(string.Format("{0}", ((CheckEdit)sender).Tag)); } 14、一个页面上各个组件之间如何互相访问属性或者方法? 可以在页面上定义一些共有的属性(只读的,public),然后组件可以访问窗体的这些属性间接地访问了其他组件的公共元素。 15、gridView1_SelectionChanged与gridView1_FocusedRowChanged的区别? gridView1_SelectionChanged 只有在 gridView1.OptionsSelection.MultiSelect = true; 的情况下才有效 当gridView1.OptionsSelection.MultiSelect = false时,可以用 gridView1_FocusedRowChanged 替代 SelectionChanged 的时候不一定触发了 FocusedRowChanged ,但 FocusedRowChanged 的时候一定触发了 SelectionChanged 事件