在Winform开发中使用日程控件XtraScheduler

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

1、日程控件的表现效果

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

日视图:

在Winform开发中使用日程控件XtraScheduler

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

在Winform开发中使用日程控件XtraScheduler

 

周视图:

在Winform开发中使用日程控件XtraScheduler

月视图:

在Winform开发中使用日程控件XtraScheduler

 

2、日程控件XtraScheduler的使用

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

1)几种视图的切换

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

在Winform开发中使用日程控件XtraScheduler

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

        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)设置禁用编辑、新增等功能处理

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

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

在Winform开发中使用日程控件XtraScheduler

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

            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)日程控件的头部日期显示处理

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

在Winform开发中使用日程控件XtraScheduler

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

在Winform开发中使用日程控件XtraScheduler

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

    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")));
        }
    }

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

            //重载头部显示
            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事件进行修改处理,如下所示。(推荐采用上面一种)

        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即可,这个事件在菜单显示前进行处理,如下面所示代码。

        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的存储,如下所示。

在Winform开发中使用日程控件XtraScheduler

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

在Winform开发中使用日程控件XtraScheduler

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

在Winform开发中使用日程控件XtraScheduler

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

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

   /// <summary>
    /// 日程资源
    /// </summary>
    [DataContract]
    public class AppResourceInfo : BaseEntity
    {
        /// <summary>
        /// 默认构造函数(需要初始化属性的在此处理)
        /// </summary>
        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; }

        /// <summary>
        /// 资源ID
        /// </summary>
        [DataMember]
        public virtual int ResourceId { get; set; }

        /// <summary>
        /// 资源名称
        /// </summary>
        [DataMember]
        public virtual string ResourceName { get; set; }

        /// <summary>
        /// 颜色
        /// </summary>
        [DataMember]
        public virtual int Color { get; set; }

        /// <summary>
        /// 图形
        /// </summary>
        [DataMember]
        public virtual byte[] Image { get; set; }

        /// <summary>
        /// 自定义
        /// </summary>
        [DataMember]
        public virtual string CustomField1 { get; set; }


        #endregion

    }

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

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

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

        /// <summary>
        /// 设置日程控件的字段映射
        /// </summary>
        /// <param name="control">日程控件</param>
        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";
        }

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

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

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

        private void btnLoadData_Click(object sender, EventArgs e)
        {
            //从数据库加载日程信息
            List<AppResourceInfo> resouceList = BLLFactory<AppResource>.Instance.GetAll();
            this.schedulerStorage1.Resources.DataSource = resouceList;

            List<UserAppointmentInfo> eventList = BLLFactory<UserAppointment>.Instance.GetAll();
            this.schedulerStorage1.Appointments.DataSource = eventList;

            if (resouceList.Count > 0)
            {
                MessageDxUtil.ShowTips("数据加载成功");
            }
            else
            {
                MessageDxUtil.ShowTips("数据库不存在记录");
            }
        }

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

        private void btnSave_Click(object sender, EventArgs e)
        {
            int count = BLLFactory<AppResource>.Instance.GetRecordCount();
            if (count == 0)
            {
                try
                {
                    foreach (AppResourceInfo info in ResourceList)
                    {
                        BLLFactory<AppResource>.Instance.Insert(info);
                    }

                    foreach (UserAppointmentInfo info in EventList)
                    {
                        BLLFactory<UserAppointment>.Instance.Insert(info);
                    }

                    MessageDxUtil.ShowTips("数据保存成功");
                }
                catch (Exception ex)
                {
                    LogTextHelper.Error(ex);
                    MessageDxUtil.ShowError(ex.Message);
                }
            }
            else
            {
                MessageDxUtil.ShowTips("数据库已存在数据");
            }
        }

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

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

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

在Winform开发中使用日程控件XtraScheduler

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

在Winform开发中使用日程控件XtraScheduler

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

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

        /// <summary>
        /// Add your code to obtain a custom field value and fill the editor with data.
        /// </summary>
        public override void LoadFormData(DevExpress.XtraScheduler.Appointment appointment)
        {                
            //加载自定义属性
            txtCustom.Text = (appointment.CustomFields["CustomField1"] == null) ? "" : appointment.CustomFields["CustomField1"].ToString();

            base.LoadFormData(appointment);
        }

        /// <summary>
        /// Add your code to retrieve a value from the editor and set the custom appointment field.
        /// </summary>
        public override bool SaveFormData(DevExpress.XtraScheduler.Appointment appointment)
        {
            //保存自定义属性
            appointment.CustomFields["CustomField1"] = txtCustom.Text;

            return base.SaveFormData(appointment);
        }

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

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

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

        /// <summary>
        /// 设置日程控件的字段映射
        /// </summary>
        /// <param name="control">日程控件</param>
        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的经验总结,其中已经考虑了数据存储和显示,以及快速开发的几个方面,当然我们可以根据这些案例,做出更好的日程应用来了。 

更多相关文章
  • 流向地图火了,因为Facebook的那张著名的友邻图,抑或因为<数据可视化之美>中介绍飞行模式的航线图,总之,流向地图以它特殊的可视化形式,直观地展示事物之间的联系,尤其在展示网络流向.贸易流向.迁徙路线等方面具有天然的优势. Flow maps - show the movement ...
  •  由于某些原因,前一段时间比较关注于系统的安全问题,因此接触到了著名的渗透系统 BackTrack.最初,BackTrack 是基于 Slackware 和 SLAX 的自启动运行光盘,包含了一套安全及计算机取证工具.此后,它还基于 Ubuntu 发布了新的 BT 版本.不过它一直以 Live CD ...
  • 索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是Hash索引. Hash索引 所谓Hash索引,当我们要给某张表某列增加索引时,将这张表的这一列进行 ...
  • VMware本周发布了一系列补丁修复多个漏洞,包括其服务器虚拟化平台. 漏洞存在于VMware的vCenter Server Appliance (vCSA)中,一个VMware vCenter服务器的一个组件.最主要的XSS漏洞(CVE-2014-3797)是由Trustware Spiderla ...
  • Number Sequence Time Limit: 2/1 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 124651    Accepted Submission(s): 30 ...
  • 昨天发布的Windows 10上配备了全新的浏览器Microsoft Edge.据官方介绍,Edge浏览器将会更加轻量,速度更快,而且还具有Cortana的功能加成.Edge几乎能让我们忘记IE带给我们的所有不愉快,但是和Chrome浏览器相比呢?两款浏览器各自的表现又如何呢?为此,外媒率先对两款浏 ...
一周排行
  • 当前,我国宽带网络发展进入了高速发展时期,政府出台了一系列政策对宽带网络建设进行指导,如七部委联合下发的<关于推进光纤宽带网络建设的意见>,工业和信息化部提出实施的“宽带普及提速工程”,以及我国的< ...
  • 自从工作室上了ADSL之后我就琢磨着如何让工作室里的局域网实现共享上网,利用宽带路由器可以轻松实现共享上网,但我又不想花费那几百元钱,如果利用软路由,需要一台配置不错的电脑作为服务器24小时开机,浪费资源.怎么办呢? ...
  •   在做一功能的过程中,需要添加信息.想着是提示添加成功后,跳转到别的页面(即用Response.Redirect语句跳转到别的页面).但是,不论我怎么修改注册客户端脚本弹窗的代码,就是不显示.代码如下(只贴出了注册 ...
  • 如今,云计算这个概念不仅仅在定义上略显不明确,特别是对于用户来说,从某种程度上宣传的已经有些过了头,使得用户正在考虑云计算是否能够给他们带来大幅的成本节约,尤其是在当前经济不景气的情况下. 而对于电信运营商来说,&q ...
  • 2013年3月,欧洲的反垃圾邮件公司Spamhaus网站遭遇史上最大流量DDoS攻击,攻击流量峰值高达300Gbps.Spamhaus是一家致力于反垃圾邮件的非盈利性组织,总部设在伦敦和日内瓦.Spamhaus维护了 ...
  • “注意!注意!一大波黑客正在涌来!” 面对着媒体报道层出不穷的黑客袭击事件,让我们在信息世界中混沌的神经突然绷紧,回望我们的信息安全太阳花,原来在它的周围早已经危机四伏!然,祸兮福所伏.危机也是带来商机,带来技术提升 ...
  • 有时候我们可能会有这样的需求,就是在编辑模式下,控制移动场景中的物体,这里面有两个点要解决: (1)怎么在编辑模式下运行一个脚本: (2)怎么有效地响应鼠标按键. 第一个问题可以使用编辑器属性ExecuteInEdi ...
  • csol将在3月19日周三进行例行的停机维护,本次维护预计需要3小时,维护期间所有的玩家都无法进行游戏,下面是详细的维护内容介绍 亲爱的战友: 我们将于03月19日0对所有服务器进行例行维护. 在 ...
  • 看看 iBATIS SQL Maps 是怎样从数据库按照 one-to-many 关系查询数据的:<?xml version="1.0" encoding="UTF-8" ...
  • 最终幻想零式HD人物之间的相性分析 人物之间的相性. 0.人物之间的关系组合有相性影响. 1.「ace.queen.nine」「jack.cinque.deuce」「sice.eight.king」「seven.ca ...