最近几天,正在学习devexpress scheduler control
的确是比较复杂。
我们先列一下,可以从哪里得到学习的资源:
https://documentation.devexpress.com/#WindowsForms/CustomDocument2278
Lesson 5 - Bind a Scheduler to MS SQL Database at Design Time
这一段是比较重要的资源。
从文档中,我们看到,可以自定义有
Lesson 7 - Create a Custom Appointment Edit Form
Lesson 8 - Implement a Custom Inplace Editor
可是,这两项,老实说,并不是真正问题的关键。
整个Scheduler体系的核心是Appointment.
因为,作为一个管理者,需要面对所有的员工的任务安排,那么这种情况下,Filter就是关键,
上图就是Devexpress 自带示例中的两个与filter相关的示例。
第一个示例,是关于电视台的,界面中,有两个维度:channels 和 sports.
虽然,只有两个维度,已经初步展示了真实世界的复杂:电视频道,和体育运动之间,有着复杂的时空关系。
但是,如果我们面对更加复杂的需求。
比如说,我们需要再加一维过滤。
比如说,我就喜欢看NBA,或者,我就只喜欢一个运动员,比如最近世锦赛里比较出名的考森斯,那么如何来加一维呢?
再比如,电视频道,是独占性资源,然而,现实世界,很多资源并不是独立性的,比如8车道高速公路,比如一个工作岗位,可能为有限数目的对象服务。
这种情况,又当如何?
所以,只有两个维度,显然是不够的。
我们先来分析一下,Appointment Filtering的示例,它的过虑代码如下:
private void schedulerStorage_FilterAppointment(object sender, PersistentObjectCancelEventArgs e) { int sportId = Convert.ToInt32(this.imcbSports.EditValue); if (sportId < 0) return; Appointment apt = (Appointment)e.Object; e.Cancel = apt.LabelId != sportId; }
看这句:
e.Cancel = apt.LabelId != sportId;
这里有一个问题,apt对象是Appointment类的一个实例。
而Appointment类,是DevExpress.XtraScheduler库的一个类。
也就是说,这个类在类库中,除非我们去重新编译devexpress的原代码,否则,我们无法改变它。
初步看了源代码,我们也无法继承这个类。因为,devexpress似乎没有提供一个注册工厂类的地方。
老实说,面对这种情况,真应当,真接把类库代码改了省事。但现在,我们还是再看看别的例子。
想到,下面还有一个例子
这个例子中,加入了新的维度。
下断了以后,我们分析一下:
也就是说,覆写了AppointmentForm类的
protected override AppointmentFormController CreateController(SchedulerControl control, Appointment apt) {
return new UserDefinedFilterAppointmentFormController(control, apt);
}
例子在填加自定义Appointment的对话框中,填加了一个自定义控制器。UserDefinedFilterAppointmentFormController的实例。
控制器的目的,就是为了扩展Appointment类,使这个类中,自定义的字段,也能够被使用。
public class UserDefinedFilterAppointmentFormController : AppointmentFormController { public UserDefinedFilterAppointmentFormController(SchedulerControl control, Appointment apt) : base(control, apt) { } public Decimal Price { get { object value = EditedAppointmentCopy.CustomFields["CustomFieldPrice"]; try { return Convert.ToDecimal(value); } catch { return 0; } } set { EditedAppointmentCopy.CustomFields["CustomFieldPrice"] = value; } } protected override void ApplyCustomFieldsValues() { base.ApplyCustomFieldsValues(); SourceAppointment.CustomFields["CustomFieldPrice"] = Price; } }
上图是调用栈。
下面,我们分析一下UserDefinedFilterModule中,过滤的实现:
关键就一句话:
private void OnBtnApplyClick(object sender, EventArgs e) { schedulerControl.Storage.Appointments.Filter = filterControlForAppointments.FilterString; }
到这就分析得差不多了。
另外,例子中,自定义字段的映射,
private void AddCustomFieldsMapping() { AppointmentCustomFieldMapping customPriceMapping = new AppointmentCustomFieldMapping("CustomFieldPrice", "Price", FieldValueType.Decimal); schedulerStorage1.Appointments.CustomFieldMappings.Add(customPriceMapping); }
其实,对我来说,更加习惯用可视化的编辑器来定义自定义映射。