在一些应用场景中,我们可能需要记录某一天,某个时段的日程安排,那么这个时候就需要引入了DevExpress的日程控件XtraScheduler了,这个控件功能非常强大,提供了很好的界面展现方式,以及很多的事件、属性给我们定制修改,能很好满足我们的日程计划安排的需求,本文全面分析并使用这个控件,希望把其中的经验与大家分享。

1、日程控件的表现效果

整个日程控件,可以分为日视图、周视图、月视图等等,当然还有一些不常用的时间线、甘特图等,本例我们来关注控件的使用以及这几个视图的处理。先来看看他们的界面效果,如下所示。

日视图:

在视图里面,默认可以打开响应的日程事件进行编辑的。

周视图:

月视图:

2、日程控件XtraScheduler的使用

我们在上面展示了这个控件的几个视图的界面,一般情况下的控件使用还是很方便的,也就是直接拖拉SchedulerControl到Winform界面即可,但是我们为了符合我们的使用需求,还是需要设置不少属性或者事件的处理的。

1)几种视图的切换

由于控件,默认也是提供右键菜单,对几种控件视图进行切换的,如下菜单所示。

但是我们也可以通过代码进行切换处理,具体代码很简单,该控件已经进行了很好的封装,直接使用即可。

  1. private void btnDayView_Click(object sender, EventArgs e)
  2. {
  3. //需要为日视图类型
  4. this.schedulerControl1.ActiveViewType = SchedulerViewType.Day;
  5. }
  6.  
  7. private void btnWeekView_Click(object sender, EventArgs e)
  8. {
  9. //需要为周视图类型
  10. this.schedulerControl1.ActiveViewType = SchedulerViewType.FullWeek;
  11. }
  12.  
  13. private void btnMonthView_Click(object sender, EventArgs e)
  14. {
  15. //需要为周视图类型
  16. this.schedulerControl1.ActiveViewType = SchedulerViewType.Month;
  17. }

2)设置禁用编辑、新增等功能处理

该日程控件,可以通过控件属性,对日程记录的新增、编辑、删除等菜单功能进行屏蔽或者开放(默认是开放的)。

通过控件属性的方式,操作如下所示。

当然我们也可以通过代码对这些属性进行设置,如下代码所示。

  1. SchedulerControl control = this.schedulerControl1;
  2.  
  3. //禁用日程增加、删除、修改、拖拉等操作
  4. control.OptionsCustomization.AllowAppointmentCreate = DevExpress.XtraScheduler.UsedAppointmentType.None;
  5. control.OptionsCustomization.AllowAppointmentDelete = DevExpress.XtraScheduler.UsedAppointmentType.None;
  6. control.OptionsCustomization.AllowAppointmentEdit = DevExpress.XtraScheduler.UsedAppointmentType.None;
  7. control.OptionsCustomization.AllowAppointmentDrag = DevExpress.XtraScheduler.UsedAppointmentType.None;
  8. control.OptionsCustomization.AllowAppointmentMultiSelect = false;
  9. control.OptionsRangeControl.AllowChangeActiveView = false;
  10. control.Views.MonthView.CompressWeekend = false;
  11. control.OptionsBehavior.ShowRemindersForm = false;

3)日程控件的头部日期显示处理

默认的日程控件,其日视图、周视图的头部默认显示的是日期,如下所示。

如果需要把它修改为我们想要的头部内容(如加上星期几),那么就需要对这个头部显示进行自定义的处理才可以了。

有两种方式可以实现这个功能, 其一是引入一个自定义类,如下所示。

  1. public class CustomHeaderCaptionService : HeaderCaptionServiceWrapper
  2. {
  3. public CustomHeaderCaptionService(IHeaderCaptionService service)
  4. : base(service)
  5. {
  6. }
  7.  
  8. public override string GetDayColumnHeaderCaption(DayHeader header)
  9. {
  10. DateTime date = header.Interval.Start.Date;
  11. return string.Format("{0:M}({1})", date, date.ToString("dddd",new System.Globalization.CultureInfo("zh-cn")));
  12. }
  13. }

然后在控件初始化后,添加对这个处理实现即可。

  1. //重载头部显示
  2. IHeaderCaptionService headerCaptionService = (IHeaderCaptionService)control.GetService(typeof(IHeaderCaptionService));
  3. if (headerCaptionService != null)
  4. {
  5. CustomHeaderCaptionService customHeaderCaptionService = new CustomHeaderCaptionService(headerCaptionService);
  6. control.RemoveService(typeof(IHeaderCaptionService));
  7. control.AddService(typeof(IHeaderCaptionService), customHeaderCaptionService);
  8. }

或者也可以重载CustomDrawDayHeader事件进行修改处理,如下所示。(推荐采用上面一种)

  1. private void schedulerControl1_CustomDrawDayHeader(object sender, CustomDrawObjectEventArgs e)
  2. {
  3. //重绘Header部分,设置日程头部显示格式
  4. SchedulerControl control = this.schedulerControl1;
  5. SchedulerViewType svt = control.ActiveViewType;
  6. if (svt == SchedulerViewType.Day || svt == SchedulerViewType.FullWeek ||
  7. svt == SchedulerViewType.Week || svt == SchedulerViewType.WorkWeek)
  8. {
  9. DayHeader header = e.ObjectInfo as DayHeader;
  10. DateTime date = header.Interval.Start;
  11. header.Caption = string.Format("{0}({1})", date.ToString("MM月d日"), date.ToString("dddd", new System.Globalization.CultureInfo("zh-cn")));
  12. }
  13. }

4)自定义菜单的处理

在日程控件XtraScheduler的使用中,我们也可以获取到控件的菜单对象,并对它进行修改、删除,或者新增自己的菜单事件也是可以的,我们实现事件PopupMenuShowing即可,这个事件在菜单显示前进行处理,如下面所示代码。

  1. private void schedulerControl1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
  2. {
  3. //对日程的右键菜单进行修改
  4. SchedulerControl control = this.schedulerControl1;
  5. if (e.Menu.Id == DevExpress.XtraScheduler.SchedulerMenuItemId.DefaultMenu)
  6. {
  7. //隐藏【视图更改为】菜单
  8. SchedulerPopupMenu itemChangeViewTo = e.Menu.GetPopupMenuById(SchedulerMenuItemId.SwitchViewMenu);
  9. itemChangeViewTo.Visible = false;
  10.  
  11. //删除【新建所有当天事件】菜单
  12. e.Menu.RemoveMenuItem(SchedulerMenuItemId.NewAllDayEvent);
  13.  
  14. //设置【新建定期日程安排】菜单为不可用
  15. e.Menu.DisableMenuItem(SchedulerMenuItemId.NewRecurringAppointment);
  16.  
  17. //改名【新建日程安排】菜单为自定义名称
  18. SchedulerMenuItem item = e.Menu.GetMenuItemById(SchedulerMenuItemId.NewAppointment);
  19. if (item != null) item.Caption = "新建一个计划";
  20.  
  21. //创建一个新项,用内置的命令
  22. ISchedulerCommandFactoryService service =
  23. (ISchedulerCommandFactoryService)control.GetService(typeof(ISchedulerCommandFactoryService));
  24. SchedulerCommand cmd = service.CreateCommand(SchedulerCommandId.PrintPreview);//打印预览
  25. SchedulerMenuItemCommandWinAdapter menuItemCommandAdapter = new SchedulerMenuItemCommandWinAdapter(cmd);
  26. DXMenuItem menuItem = (DXMenuItem)menuItemCommandAdapter.CreateMenuItem(DXMenuItemPriority.Normal);
  27. menuItem.BeginGroup = true;
  28. e.Menu.Items.Add(menuItem);
  29.  
  30. //创建一个新的自定义事件菜单
  31. DXMenuItem menuTest = new SchedulerMenuItem("测试菜单");
  32. menuTest.Click += menuItem2_Click;
  33. menuTest.BeginGroup = true;
  34. e.Menu.Items.Add(menuTest);
  35. }
  36.  
  37. }
  38.  
  39. void menuItem2_Click(object sender, EventArgs e)
  40. {
  41. MessageDxUtil.ShowTips("测试菜单功能");
  42. }

3、日程控件XtraScheduler的数据绑定

在日程控件里面,我们最重要,最关注的莫过于它的数据绑定及内容显示了,因为只有这样,我们才可以用于实价的应用当中,为用户显示他所需的数据,并存储我们所需要的数据。

在日程控件里面,有相应的引导我们进行这样的处理,还是非常不错的。

数据的绑定,我们需要了解日程控件的默认处理方式,因为它也提供了一些数据字段的信息,我们从控件的对象里面,看到有创建数据库的信息,里面有一些表的字段,我们可以参考来创建我们的数据存储信息,其中就包括了资源Resource的存储,日程事件安排Appointments的存储,如下所示。

根据这个里面的字段信息,我们可以建立自己的数据库模型如下所示。

在数据库里面创建这两个表,并根据这些表对象,使用代码生成工具Database2Sharp进行代码的快速生成,然后复制生成的代码到具体的测试项目里面,生成的代码无需任何修改即可直接使用在具体项目里面,测试项目如下代码结构所示。

如日程资源对象的数据库信息,就会转换为具体的实体类信息,供我们在界面中使用了,这样也符合我的Winform开发框架的实体类绑定规则,提高我们数据的强类型约束。

如资源对象的实体类代码生成如下所示。

  1. /// <summary>
  2. /// 日程资源
  3. /// </summary>
  4. [DataContract]
  5. public class AppResourceInfo : BaseEntity
  6. {
  7. /// <summary>
  8. /// 默认构造函数(需要初始化属性的在此处理)
  9. /// </summary>
  10. public AppResourceInfo()
  11. {
  12. this.ID = ;
  13. this.ResourceId = ;
  14. this.Color = ;
  15. this.Image = new byte[] { };
  16. }
  17.  
  18. #region Property Members
  19.  
  20. [DataMember]
  21. public virtual int ID { get; set; }
  22.  
  23. /// <summary>
  24. /// 资源ID
  25. /// </summary>
  26. [DataMember]
  27. public virtual int ResourceId { get; set; }
  28.  
  29. /// <summary>
  30. /// 资源名称
  31. /// </summary>
  32. [DataMember]
  33. public virtual string ResourceName { get; set; }
  34.  
  35. /// <summary>
  36. /// 颜色
  37. /// </summary>
  38. [DataMember]
  39. public virtual int Color { get; set; }
  40.  
  41. /// <summary>
  42. /// 图形
  43. /// </summary>
  44. [DataMember]
  45. public virtual byte[] Image { get; set; }
  46.  
  47. /// <summary>
  48. /// 自定义
  49. /// </summary>
  50. [DataMember]
  51. public virtual string CustomField1 { get; set; }
  52.  
  53. #endregion
  54.  
  55. }

有了这些对象,我们还需要做的就是绑定控件和保存控件数据到数据库里面的处理。

但是这里还需要注意一个问题就是,这个日程控件数据是通过字段映射的方式进行数据绑定的,也就是它本身也提供了几个常规字段的信息,因此我们需要把它们的属性和数据库的字段(这里是实体类)的信息进行匹配。

如我们可以通过绑定如下,事项Appointments和Resources的Mappings处理。

  1. /// <summary>
  2. /// 设置日程控件的字段映射
  3. /// </summary>
  4. /// <param name="control">日程控件</param>
  5. private void SetMappings(SchedulerControl control)
  6. {
  7. AppointmentMappingInfo appoint = control.Storage.Appointments.Mappings;
  8. appoint.AllDay = "AllDay";
  9. appoint.Description = "Description";
  10. appoint.End = "EndDate";
  11. appoint.Label = "AppLabel";
  12. appoint.Location = "Location";
  13. appoint.RecurrenceInfo = "RecurrenceInfo";
  14. appoint.ReminderInfo = "ReminderInfo";
  15. appoint.ResourceId = "ResourceId";
  16. appoint.Start = "StartDate";
  17. appoint.Status = "Status";
  18. appoint.Subject = "Subject";
  19. appoint.Type = "EventType";
  20.  
  21. ResourceMappingInfo res = control.Storage.Resources.Mappings;
  22. res.Caption = "ResourceName";
  23. res.Color = "Color";
  24. res.Id = "ResourceId";
  25. res.Image = "Image";
  26. }

确定控件属性和实体类之间关系后,我们就需要从数据库里面加载信息了。我们在窗体的代码里面增加两个资源对象的集合列表,如下代码所示。

  1. //日程资源集合和事件列表
  2. private List<AppResourceInfo> ResourceList = new List<AppResourceInfo>();
  3. private List<UserAppointmentInfo> EventList = new List<UserAppointmentInfo>();

然后就是把数据从数据库里面,通过开发框架底层的工厂类进行数据的提取,如下代码所示。

  1. private void btnLoadData_Click(object sender, EventArgs e)
  2. {
  3. //从数据库加载日程信息
  4. List<AppResourceInfo> resouceList = BLLFactory<AppResource>.Instance.GetAll();
  5. this.schedulerStorage1.Resources.DataSource = resouceList;
  6.  
  7. List<UserAppointmentInfo> eventList = BLLFactory<UserAppointment>.Instance.GetAll();
  8. this.schedulerStorage1.Appointments.DataSource = eventList;
  9.  
  10. if (resouceList.Count > )
  11. {
  12. MessageDxUtil.ShowTips("数据加载成功");
  13. }
  14. else
  15. {
  16. MessageDxUtil.ShowTips("数据库不存在记录");
  17. }
  18. }

而保存数据,我们把对象里面的集合存储到数据库里面即可。

  1. private void btnSave_Click(object sender, EventArgs e)
  2. {
  3. int count = BLLFactory<AppResource>.Instance.GetRecordCount();
  4. if (count == )
  5. {
  6. try
  7. {
  8. foreach (AppResourceInfo info in ResourceList)
  9. {
  10. BLLFactory<AppResource>.Instance.Insert(info);
  11. }
  12.  
  13. foreach (UserAppointmentInfo info in EventList)
  14. {
  15. BLLFactory<UserAppointment>.Instance.Insert(info);
  16. }
  17.  
  18. MessageDxUtil.ShowTips("数据保存成功");
  19. }
  20. catch (Exception ex)
  21. {
  22. LogTextHelper.Error(ex);
  23. MessageDxUtil.ShowError(ex.Message);
  24. }
  25. }
  26. else
  27. {
  28. MessageDxUtil.ShowTips("数据库已存在数据");
  29. }
  30. }

这样,通过代码工具Database2Sharp生成的代码,直接具有数据存储和获取的功能,例子就很容易明白和处理了,在实际的项目中,我们可能还需要存储用户的额外信息,如公司、部门、自定义信息等等,当然也可以通过这样的模式进行快速的开发,从而实现高效、统一、稳定的系统开发过程。

但是,言归正传,我们前面介绍的字段,都是控件里面有的内容,如果是控件里面没有,我们需要增加的自定义属性,那么我们应该如何处理呢,还有默认的日程界面可以修改吗,等等这些也是我们经常会碰到的问题。

首先我们在日程控件界面上,通过连接按钮的方式,创建一个自定义的日程窗体,如下所示

这样我们就可以看到,在项目里面增加了一个日程编辑框了,打开窗体界面,并增加一个自定义的控件内容,最终界面如下所示。

默认的后台代码里面,具有了LoadFormData和SaveFormData两个重载的方法,这里就是留给我们对自定义属性进行处理的方法体了。

我们在其中增加部分自定义属性字段的映射处理即可,如下代码所示。

  1. /// <summary>
  2. /// Add your code to obtain a custom field value and fill the editor with data.
  3. /// </summary>
  4. public override void LoadFormData(DevExpress.XtraScheduler.Appointment appointment)
  5. {
  6. //加载自定义属性
  7. txtCustom.Text = (appointment.CustomFields["CustomField1"] == null) ? "" : appointment.CustomFields["CustomField1"].ToString();
  8.  
  9. base.LoadFormData(appointment);
  10. }
  11.  
  12. /// <summary>
  13. /// Add your code to retrieve a value from the editor and set the custom appointment field.
  14. /// </summary>
  15. public override bool SaveFormData(DevExpress.XtraScheduler.Appointment appointment)
  16. {
  17. //保存自定义属性
  18. appointment.CustomFields["CustomField1"] = txtCustom.Text;
  19.  
  20. return base.SaveFormData(appointment);
  21. }

然后我们记得在主体窗体的映射里面,为他们增加对应的字段映射即可,映射代码如下所示。

  1. AppointmentCustomFieldMappingCollection appointCust = control.Storage.Appointments.CustomFieldMappings;
  2. appointCust.Add(new AppointmentCustomFieldMapping("CustomField1","CustomField1"));

这样就构成了一个完整的映射信息。

  1. /// <summary>
  2. /// 设置日程控件的字段映射
  3. /// </summary>
  4. /// <param name="control">日程控件</param>
  5. private void SetMappings(SchedulerControl control)
  6. {
  7. AppointmentMappingInfo appoint = control.Storage.Appointments.Mappings;
  8. appoint.AllDay = "AllDay";
  9. appoint.Description = "Description";
  10. appoint.End = "EndDate";
  11. appoint.Label = "AppLabel";
  12. appoint.Location = "Location";
  13. appoint.RecurrenceInfo = "RecurrenceInfo";
  14. appoint.ReminderInfo = "ReminderInfo";
  15. appoint.ResourceId = "ResourceId";
  16. appoint.Start = "StartDate";
  17. appoint.Status = "Status";
  18. appoint.Subject = "Subject";
  19. appoint.Type = "EventType";
  20.  
  21. AppointmentCustomFieldMappingCollection appointCust = control.Storage.Appointments.CustomFieldMappings;
  22. appointCust.Add(new AppointmentCustomFieldMapping("CustomField1","CustomField1"));
  23.  
  24. ResourceMappingInfo res = control.Storage.Resources.Mappings;
  25. res.Caption = "ResourceName";
  26. res.Color = "Color";
  27. res.Id = "ResourceId";
  28. res.Image = "Image";
  29. }

以上就是我在整合日程控件XtraScheduler的经验总结,其中已经考虑了数据存储和显示,以及快速开发的几个方面,当然我们可以根据这些案例,做出更好的日程应用来了。

在Winform开发中使用日程控件XtraScheduler的更多相关文章

  1. 在Winform开发中使用日程控件XtraScheduler(2)--深入理解数据的存储

    在上篇随笔<在Winform开发中使用日程控件XtraScheduler>中介绍了DevExpress的XtraScheduler日程控件的各种使用知识点,对于我们来说,日程控件不陌生,如 ...

  2. WinForm开发中针对TreeView控件改变当前选择节点的字体与颜色

    本文转载:http://www.cnblogs.com/umplatform/archive/2012/08/29/2660240.html 在B/S开发中,对TreeView控件要改变当前选中节点的 ...

  3. C#里WinForm开发中如何实现控件随窗体大小的改变而自动适应其改变(转)

    在设计可供用户调整大小的窗体时,如何实现该窗体上的控件也应能正确地随窗体的改变而自动调整大小并且能重新定位?此时就要借助控件的.Anchor属性.Anchor属性定义控件的定位点位置.当控件锚定到某个 ...

  4. Winform开发中如何将数据库字段绑定到ComboBox控件

    最近开始自己动手写一个财务分析软件,由于自己也是刚学.Net不久,所以自己写的的时候遇到了很多问题,希望通过博客把一些印象深刻的问题记录下来. Winform开发中如何将数据库字段绑定到ComboBo ...

  5. WinForm开发中通用附件管理控件设计开发参考

    1.引言 在WinForm开发中,文件附件的管理几乎在任何一个应用上都会存在,是一个非常通用集中的公共模块.我们日常记录会伴随着有图片.文档等附件形式来展现,如果为每个业务对象都做一个附件管理,或者每 ...

  6. dhtmlxScheduler日历日程控件包括天视图,周视图,月视图,年视图和日程表视图

    dhtmlxScheduler 是一个基于Web的类似于Outlook的日历日程控件. 它完全由javascript/js/css编写, 提供类似于MS Outlook Calendar, Apple ...

  7. 在Winform开发中使用Grid++报表

    之前一直使用各种报表工具,如RDLC.DevExpress套件的XtraReport报表,在之前一些随笔也有介绍,最近接触锐浪的Grid++报表,做了一些测试例子和辅助类来处理报表内容,觉得还是很不错 ...

  8. 在Winform开发中使用FastReport创建报表

    FastReport.Net是一款适用于Windows Forms, ASP.NET和MVC框架的功能齐全的报表分析解决方案.可用在Microsoft Visual Studio 2005到2015, ...

  9. 在Winform开发中,我们使用的几种下拉列表展示字典数据的方式

    在Winform开发中中,我们为了方便客户选择,往往使用系统的字典数据选择,毕竟选择总比输入来的快捷.统一,一般我们都会简单封装一下,以便方便对控件的字典值进行展示处理,本篇随笔介绍DevExpres ...

随机推荐

  1. 《CLR.via.C#第三版》第一部分读书笔记(一)

    最近开始仔细研读<CLR.via.C#第三版>这本书.读pdf文档确实很累.建议有条件的朋友还是买书看吧. 我的笔记用来记录我对这本书的理解,简化下逻辑,对每个部分我觉得是要点的进行归纳总 ...

  2. 在.net中使用aquiles访问Cassandra(四)

    数据的持久化我们都已经完成了,和所有应有程序一样,最重要的是要向用户展示数据.下面我们就推出这部分代码,读取任意行任何列: public IList<TRowResult> Execute ...

  3. [php入门] 4、HTML基础入门一篇概览

    [php入门] 1.从安装开发环境环境到(庄B)做个炫酷的登陆应用 [php入门] 2.基础核心语法大纲 [php入门] 3.WAMP中的集成MySQL相关基础操作 1.HTML的作用 HTML是超文 ...

  4. 【译】用jQuery 处理XML--浏览器中的XML与JavaScript

    用jQuery 处理XML--写在前面的话 用jQuery 处理XML-- DOM(文本对象模型)简介 用jQuery 处理XML--浏览器中的XML与JavaScript 用jQuery 处理XML ...

  5. 大叔也说Xamarin~Android篇~支付宝SDK的集成

    回到目录 首先做为支付宝SDK它提供了多种平台,网页版,wap版,IOS版,android版等等,今天主要说一下在xamarin里使用android平台的sdk的方法,在网上介绍这块的文章不多,大叔本 ...

  6. salesforce 零基础学习(三十五) 通过Process Builder和Approval Processes锁定记录(Lock Record)

    有的时候我们可能有这样的需求,当某个字段为特定的值情况下,便锁定此条记录,仅允许Profile为System Admin的用户修改或者解锁,其他的用户只能查看此条记录,不能修改此条记录,这种情况下我们 ...

  7. js,格式化long类型日期封装

    /** * 扩展date函数 * author:c3gen */ Date.prototype.format = function(format) { var o = { "M+" ...

  8. ViewPager 的页面重置问题

    当我们使用ViewPager控件时,假设我们的ViewPager有三页,当我们第一次启动ViewPager显示第一页的时候,ViewPager会预加载第二页,这样当我们向第二页滑动的时候就可以看见第二 ...

  9. Python数组合并

    Python数组合并 a = [1, 2] b = [3, 4] c = a + b print(c) # [1, 2, 3, 4]

  10. IDE:Eclipse查看接口实现类快捷键

    1.打开接口类 2.双击接口名选中 3.Ctrl+T,打开接口实现类