在一些應用場景中,咱們可能須要記錄某一天,某個時段的日程安排,那麼這個時候就須要引入了 DevExpress 的日程控件XtraScheduler 了,這個控件功能很是強大,提供了很好的界面展示方式,以及不少的事件、屬性給咱們定製修改,能很好知足咱們的日程計劃安排的需求,本文全面分析並使用這 個控件,但願把其中的經驗與你們分享。html
| 當即下載DevExpress安裝包,免費體驗30天!數據庫
一、日程控件的表現效果
整個日程控件,能夠分爲日視圖、周視圖、月視圖等等,固然還有一些不經常使用的時間線、甘特圖等,本例咱們來關注控件的使用以及這幾個視圖的處理。先來看看他們的界面效果,以下所示。微信
日視圖:app
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
在視圖裏面,默承認以打開響應的日程事件進行編輯的。框架
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
周視圖:ide
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
月視圖:函數
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
二、日程控件XtraScheduler的使用
咱們在上面展現了這個控件的幾個視圖的界面,通常狀況下的控件使用仍是很方便的,也就是直接拖拉SchedulerControl到Winform界面便可,可是咱們爲了符合咱們的使用需求,仍是須要設置很多屬性或者事件的處理的。工具
1)幾種視圖的切換
因爲控件,默認也是提供右鍵菜單,對幾種控件視圖進行切換的,以下菜單所示。測試
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
可是咱們也能夠經過代碼進行切換處理,具體代碼很簡單,該控件已經進行了很好的封裝,直接使用便可。this
[csharp] view plain copy
- 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)設置禁用編輯、新增等功能處理
該日程控件,能夠經過控件屬性,對日程記錄的新增、編輯、刪除等菜單功能進行屏蔽或者開放(默認是開放的)。
經過控件屬性的方式,操做以下所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
固然咱們也能夠經過代碼對這些屬性進行設置,以下代碼所示。
[csharp] view plain copy
- 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)日程控件的頭部日期顯示處理
默認的日程控件,其日視圖、周視圖的頭部默認顯示的是日期,以下所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
若是須要把它修改成咱們想要的頭部內容(如加上星期幾),那麼就須要對這個頭部顯示進行自定義的處理才能夠了。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
有兩種方式能夠實現這個功能, 其一是引入一個自定義類,以下所示。
[csharp] view plain copy
- 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")));
- }
- }
而後在控件初始化後,添加對這個處理實現便可。
[csharp] view plain copy
- //重載頭部顯示
- 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事件進行修改處理,以下所示。(推薦採用上面一種)
[csharp] view plain copy
- 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便可,這個事件在菜單顯示前進行處理,以下面所示代碼。
[csharp] view plain copy
- 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("測試菜單功能");
- }
三、日程控件XtraScheduler的數據綁定
在日程控件裏面,咱們最重要,最關注的莫過於它的數據綁定及內容顯示了,由於只有這樣,咱們才能夠用於實價的應用當中,爲用戶顯示他所需的數據,並存儲咱們所須要的數據。
在日程控件裏面,有相應的引導咱們進行這樣的處理,仍是很是不錯的。
數據的綁定,咱們須要瞭解日程控件的默認處理方式,由於它也提供了一些數據字段的信息,咱們從控件的對象裏面,看到有建立數據庫的信息,裏面有一些 表的字段,咱們能夠參考來建立咱們的數據存儲信息,其中就包括了資源Resource的存儲,日程事件安排Appointments的存儲,以下所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
根據這個裏面的字段信息,咱們能夠創建本身的數據庫模型以下所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
在數據庫裏面建立這兩個表,並根據這些表對象,使用代碼生成工具Database2Sharp進行代碼的快速生成,而後複製生成的代碼到具體的測試項目裏面,生成的代碼無需任何修改便可直接使用在具體項目裏面,測試項目以下代碼結構所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
如日程資源對象的數據庫信息,就會轉換爲具體的實體類信息,供咱們在界面中使用了,這樣也符合個人Winform開發框架的實體類綁定規則,提升咱們數據的強類型約束。
如資源對象的實體類代碼生成以下所示。
[csharp] view plain copy
- /// <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處理。
[csharp] view plain copy
- /// <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";
- }
肯定控件屬性和實體類之間關係後,咱們就須要從數據庫裏面加載信息了。咱們在窗體的代碼裏面增長兩個資源對象的集合列表,以下代碼所示。
[csharp] view plain copy
- //日程資源集合和事件列表
- private List<AppResourceInfo> ResourceList = new List<AppResourceInfo>();
- private List<UserAppointmentInfo> EventList = new List<UserAppointmentInfo>();
而後就是把數據從數據庫裏面,經過開發框架底層的工廠類進行數據的提取,以下代碼所示。
[csharp] view plain copy
- 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("數據庫不存在記錄");
- }
- }
而保存數據,咱們把對象裏面的集合存儲到數據庫裏面便可。
[csharp] view plain copy
- 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生成的代碼,直接具備數據存儲和獲取的功能,例子就很容易明白和處理了,在實際的項目中,咱們可能 還須要存儲用戶的額外信息,如公司、部門、自定義信息等等,固然也能夠經過這樣的模式進行快速的開發,從而實現高效、統1、穩定的系統開發過程。
可是,言歸正傳,咱們前面介紹的字段,都是控件裏面有的內容,若是是控件裏面沒有,咱們須要增長的自定義屬性,那麼咱們應該如何處理呢,還有默認的日程界面能夠修改嗎,等等這些也是咱們常常會碰到的問題。
首先咱們在日程控件界面上,經過鏈接按鈕的方式,建立一個自定義的日程窗體,以下所示:
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
這樣咱們就能夠看到,在項目裏面增長了一個日程編輯框了,打開窗體界面,並增長一個自定義的控件內容,最終界面以下所示。
![DevExpress日程控件](http://static.javashuo.com/static/loading.gif)
默認的後臺代碼裏面,具備了LoadFormData和SaveFormData兩個重載的方法,這裏就是留給咱們對自定義屬性進行處理的方法體了。
咱們在其中增長部分自定義屬性字段的映射處理便可,以下代碼所示。
[csharp] view plain copy
- /// <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);
- }
而後咱們記得在主體窗體的映射裏面,爲他們增長對應的字段映射便可,映射代碼以下所示。
[csharp] view plain copy
- AppointmentCustomFieldMappingCollection appointCust = control.Storage.Appointments.CustomFieldMappings;
- appointCust.Add(new AppointmentCustomFieldMapping("CustomField1","CustomField1"));
這樣就構成了一個完整的映射信息。
[csharp] view plain copy
- /// <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的經驗總結,其中已經考慮了數據存儲和顯示,以及快速開發的幾個方面,固然咱們能夠根據這些案例,作出更好的日程應用來了。
by 伍華聰
![](http://static.javashuo.com/static/loading.gif)
===============================================================
更多精彩預告請持續關注DevExpress中文網!
掃描關注DevExpress中文網微信公衆號,及時獲取最新動態及最新資訊
![DevExpress中文網微信](http://static.javashuo.com/static/loading.gif)