DevExpress XtraScheduler日程管理控件应用实例(1)-- 基本使用

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

1、日程控件的表现效果

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

日视图:

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

周视图:

月视图:

2、日程控件XtraScheduler的使用

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

1)几种视图的切换

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4)自定义菜单的处理

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

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
private void schedulerControl1_PopupMenuShowing( object sender, PopupMenuShowingEventArgs e)
         {
             //对日程的右键菜单进行修改
             SchedulerControl control =  this .schedulerControl1;
             if (e.Menu.Id == DevExpress.XtraScheduler.SchedulerMenuItemId.DefaultMenu)
             {
                 //隐藏【视图更改为】菜单
                 SchedulerPopupMenu itemChangeViewTo = e.Menu.GetPopupMenuById(SchedulerMenuItemId.SwitchViewMenu);
                 itemChangeViewTo.Visible =  false ;
 
                 //删除【新建所有当天事件】菜单
                 e.Menu.RemoveMenuItem(SchedulerMenuItemId.NewAllDayEvent);
 
                 //设置【新建定期日程安排】菜单为不可用
                 e.Menu.DisableMenuItem(SchedulerMenuItemId.NewRecurringAppointment);
 
                 //改名【新建日程安排】菜单为自定义名称
                 SchedulerMenuItem item = e.Menu.GetMenuItemById(SchedulerMenuItemId.NewAppointment);
                 if (item !=  null ) item.Caption =  "新建一个计划" ;
 
                 //创建一个新项,用内置的命令
                 ISchedulerCommandFactoryService service =
                     (ISchedulerCommandFactoryService)control.GetService( typeof (ISchedulerCommandFactoryService));
                 SchedulerCommand cmd = service.CreateCommand(SchedulerCommandId.PrintPreview); //打印预览
                 SchedulerMenuItemCommandWinAdapter menuItemCommandAdapter =  new SchedulerMenuItemCommandWinAdapter(cmd);
                 DXMenuItem menuItem = (DXMenuItem)menuItemCommandAdapter.CreateMenuItem(DXMenuItemPriority.Normal);
                 menuItem.BeginGroup =  true ;
                 e.Menu.Items.Add(menuItem);
 
                 //创建一个新的自定义事件菜单
                 DXMenuItem menuTest =  new SchedulerMenuItem( "测试菜单" );
                 menuTest.Click += menuItem2_Click;
                 menuTest.BeginGroup =  true ;
                 e.Menu.Items.Add(menuTest);
             }
 
         }
 
         void menuItem2_Click( object sender, EventArgs e)
         {
             MessageDxUtil.ShowTips( "测试菜单功能" );
         }

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

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

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

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

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

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

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

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

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
///
     /// 日程资源
     ///
     [DataContract]
     public class AppResourceInfo : BaseEntity
     {
         ///
         /// 默认构造函数(需要初始化属性的在此处理)
         ///
         public AppResourceInfo()
         {
             this .ID = 0;
             this .ResourceId = 0;
             this .Color = 0;
             this .Image =  new byte [] { };
         }
 
         #region Property Members
 
         [DataMember]
         public virtual int ID {  get set ; }
 
         ///
         /// 资源ID
         ///
         [DataMember]
         public virtual int ResourceId {  get set ; }
 
         ///
         /// 资源名称
         ///
         [DataMember]
         public virtual string ResourceName {  get set ; }
 
         ///
         /// 颜色
         ///
         [DataMember]
         public virtual int Color {  get set ; }
 
         ///
         /// 图形
         ///
         [DataMember]
         public virtual byte [] Image {  get set ; }
 
         ///
         /// 自定义
         ///
         [DataMember]
         public virtual string CustomField1 {  get set ; }
 
 
         #endregion
 
     }

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

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

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

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
///
         /// 设置日程控件的字段映射
         ///
         /// 日程控件
         private void SetMappings(SchedulerControl control)
         {
             AppointmentMappingInfo appoint = control.Storage.Appointments.Mappings;
             appoint.AllDay =  "AllDay" ;
             appoint.Description =  "Description" ;
             appoint.End =  "EndDate" ;
             appoint.Label =  "AppLabel" ;
             appoint.Location =  "Location" ;
             appoint.RecurrenceInfo =  "RecurrenceInfo" ;
             appoint.ReminderInfo =  "ReminderInfo" ;
             appoint.ResourceId =  "ResourceId" ;
             appoint.Start =  "StartDate" ;
             appoint.Status =  "Status" ;
             appoint.Subject =  "Subject" ;
             appoint.Type =  "EventType" ;
 
             ResourceMappingInfo res = control.Storage.Resources.Mappings;
             res.Caption =  "ResourceName" ;
             res.Color =  "Color" ;
             res.Id =  "ResourceId" ;
             res.Image =  "Image" ;
         }

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

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

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

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

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

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
private void btnSave_Click( object sender, EventArgs e)
         {
             int count = BLLFactory.Instance.GetRecordCount();
             if (count == 0)
             {
                 try
                 {
                     foreach (AppResourceInfo info  in ResourceList)
                     {
                         BLLFactory.Instance.Insert(info);
                     }
 
                     foreach (UserAppointmentInfo info  in EventList)
                     {
                         BLLFactory.Instance.Insert(info);
                     }
 
                     MessageDxUtil.ShowTips( "数据保存成功" );
                 }
                 catch (Exception ex)
                 {
                     LogTextHelper.Error(ex);
                     MessageDxUtil.ShowError(ex.Message);
                 }
             }
             else
             {
                 MessageDxUtil.ShowTips( "数据库已存在数据" );
             }
         }

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

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

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

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

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

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

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

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

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

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

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
///
         /// 设置日程控件的字段映射
         ///
         /// 日程控件
         private void SetMappings(SchedulerControl control)
         {
             AppointmentMappingInfo appoint = control.Storage.Appointments.Mappings;
             appoint.AllDay =  "AllDay" ;
             appoint.Description =  "Description" ;
             appoint.End =  "EndDate" ;
             appoint.Label =  "AppLabel" ;
             appoint.Location =  "Location" ;
             appoint.RecurrenceInfo =  "RecurrenceInfo" ;
             appoint.ReminderInfo =  "ReminderInfo" ;
             appoint.ResourceId =  "ResourceId" ;
             appoint.Start =  "StartDate" ;
             appoint.Status =  "Status" ;
             appoint.Subject =  "Subject" ;
             appoint.Type =  "EventType" ;
 
             AppointmentCustomFieldMappingCollection appointCust = control.Storage.Appointments.CustomFieldMappings;
             appointCust.Add( new AppointmentCustomFieldMapping( "CustomField1" , "CustomField1" ));
 
             ResourceMappingInfo res = control.Storage.Resources.Mappings;
             res.Caption =  "ResourceName" ;
             res.Color =  "Color" ;
             res.Id =  "ResourceId" ;
             res.Image =  "Image" ;
         }

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

【年末狂欢】慧都控件百厂约惠

你可能感兴趣的:(DevExpress XtraScheduler日程管理控件应用实例(1)-- 基本使用)