圖文詳解!DevExpress XtraScheduler日程管理控制元件應用例項(1)-- 基本使用

AABBbaby發表於2018-02-13

在一些應用場景中,我們可能需要記錄某一天,某個時段的日程安排,那麼這個時候就需要引入了 DevExpress 的日程控制元件XtraScheduler 了,這個控制元件功能非常強大,提供了很好的介面展現方式,以及很多的事件、屬性給我們定製修改,能很好滿足我們的日程計劃安排的需求,本文全面分析並使用這 個控制元件,希望把其中的經驗與大家分享。

立即下載DevExpress安裝包,免費體驗30天!

1、日程控制元件的表現效果

整個日程控制元件,可以分為日檢視、周檢視、月檢視等等,當然還有一些不常用的時間線、甘特圖等,本例我們來關注控制元件的使用以及這幾個檢視的處理。先來看看他們的介面效果,如下所示。

日檢視:

DevExpress日程控制元件

在檢視裡面,預設可以開啟響應的日程事件進行編輯的。

DevExpress日程控制元件

周檢視:

DevExpress日程控制元件

月檢視:

DevExpress日程控制元件

2、日程控制元件XtraScheduler的使用

我們在上面展示了這個控制元件的幾個檢視的介面,一般情況下的控制元件使用還是很方便的,也就是直接拖拉SchedulerControl到Winform介面即可,但是我們為了符合我們的使用需求,還是需要設定不少屬性或者事件的處理的。

1)幾種檢視的切換

由於控制元件,預設也是提供右鍵選單,對幾種控制元件檢視進行切換的,如下選單所示。

DevExpress日程控制元件

但是我們也可以通過程式碼進行切換處理,具體程式碼很簡單,該控制元件已經進行了很好的封裝,直接使用即可。

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日程控制元件

當然我們也可以通過程式碼對這些屬性進行設定,如下程式碼所示。

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日程控制元件

如果需要把它修改為我們想要的頭部內容(如加上星期幾),那麼就需要對這個頭部顯示進行自定義的處理才可以了。

DevExpress日程控制元件

有兩種方式可以實現這個功能, 其一是引入一個自定義類,如下所示。

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

DevExpress日程控制元件

根據這個裡面的欄位資訊,我們可以建立自己的資料庫模型如下所示。

DevExpress日程控制元件

在資料庫裡面建立這兩個表,並根據這些表物件,使用程式碼生成工具Database2Sharp進行程式碼的快速生成,然後複製生成的程式碼到具體的測試專案裡面,生成的程式碼無需任何修改即可直接使用在具體專案裡面,測試專案如下程式碼結構所示。

DevExpress日程控制元件

如日程資源物件的資料庫資訊,就會轉換為具體的實體類資訊,供我們在介面中使用了,這樣也符合我的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生成的程式碼,直接具有資料儲存和獲取的功能,例子就很容易明白和處理了,在實際的專案中,我們可能 還需要儲存使用者的額外資訊,如公司、部門、自定義資訊等等,當然也可以通過這樣的模式進行快速的開發,從而實現高效、統一、穩定的系統開發過程。

但是,言歸正傳,我們前面介紹的欄位,都是控制元件裡面有的內容,如果是控制元件裡面沒有,我們需要增加的自定義屬性,那麼我們應該如何處理呢,還有預設的日程介面可以修改嗎,等等這些也是我們經常會碰到的問題。

首先我們在日程控制元件介面上,通過連線按鈕的方式,建立一個自定義的日程窗體,如下所示:

DevExpress日程控制元件

這樣我們就可以看到,在專案裡面增加了一個日程編輯框了,開啟窗體介面,並增加一個自定義的控制元件內容,最終介面如下所示。

DevExpress日程控制元件

預設的後臺程式碼裡面,具有了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的經驗總結,其中已經考慮了資料儲存和顯示,以及快速開發的幾個方面,當然我們可以根據這些案例,做出更好的日程應用來了。 

by 伍華聰

===============================================================
更多精彩預告請持續關注DevExpress中文網!
 掃描關注DevExpress中文網微信公眾號,及時獲取最新動態及最新資訊
DevExpress中文網微信

相關文章