当前位置:   article > 正文

devexpress 甘特图总结

devexpress 甘特图

问题的提出


无意中,看了看甘特图的绘制。


在示例中,我们看到一些其它的类型中,没有的信息:


见上图,

普通的Scheduler Control 中,只是一个简单的二维图形。

但甘特图,相对而言,多出了一些信息。


那么这些信息,在哪里,是我们首先需要关心的问题。

双击一个Appointment ,看到弹出的框中,也多出一条信息:



那么,这条信息来自于哪里呢?


经过前面的总结,我们发现,SchedulerControl 的重点是其绑定的schedulerStorage控件。

            this.schedulerStorage1.AppointmentDependencies.DataSource = this.taskDependenciesBindingSource;


甘特图由几部分信息构成:

1. 资源resource。这是甘特图的基础。资源有几种可能。一般我们在Project上看到的,是工作任务。用来描述工作任务的前后衔接关系。

前提这,这些任务所需要的资源,有依赖性。如人员的工作时间。


2. 任务:Appointment



注意,我们看到,比其它的相对简单的任务设置,多出了两个字段,特别是,PercentComplete,这个项,与Appointment的编辑对话框里的信息,是对应的。

3.任务的 依赖关系的描述。devExprss中,采用的是自相关表。



好了,现在来看,信息,已经足够了。

我们来分析,如何组合这些信息,使界面能够正确显示。



具体过程

这一段代码,在design.cs中,比较直观,看完我也就不多说什么了。
          this.schedulerStorage1.AppointmentDependencies.DataSource = this.taskDependenciesBindingSource;
            this.schedulerStorage1.AppointmentDependencies.Mappings.DependentId = "Dependent";
            this.schedulerStorage1.AppointmentDependencies.Mappings.ParentId = "Parent";
            this.schedulerStorage1.AppointmentDependencies.Mappings.Type = "Type";


            this.schedulerStorage1.Appointments.CommitIdToDataSource = false;//为了解决更新时,ID的问题。
            this.schedulerStorage1.Appointments.DataSource = this.tasksBindingSource;
            this.schedulerStorage1.Appointments.Mappings.AllDay = "AllDay";
            this.schedulerStorage1.Appointments.Mappings.AppointmentId = "Id";
            this.schedulerStorage1.Appointments.Mappings.Description = "Description";
            this.schedulerStorage1.Appointments.Mappings.End = "EndTime";
            this.schedulerStorage1.Appointments.Mappings.Label = "Label";
            this.schedulerStorage1.Appointments.Mappings.Location = "Location";
            this.schedulerStorage1.Appointments.Mappings.PercentComplete = "PercentComplete"; //普通的甘特图中,没有此项。
            this.schedulerStorage1.Appointments.Mappings.RecurrenceInfo = "RecurrenceInfo";
            this.schedulerStorage1.Appointments.Mappings.ReminderInfo = "ReminderInfo";
            this.schedulerStorage1.Appointments.Mappings.ResourceId = "ResourceId";
            this.schedulerStorage1.Appointments.Mappings.Start = "StartTime";
            this.schedulerStorage1.Appointments.Mappings.Subject = "Subject";
            this.schedulerStorage1.Appointments.Mappings.Type = "EventType";


            this.schedulerStorage1.Resources.CustomFieldMappings.Add(new DevExpress.XtraScheduler.ResourceCustomFieldMapping("DaysPlanned", "DaysPlanned"));
            this.schedulerStorage1.Resources.DataSource = this.resourcesBindingSource;
            this.schedulerStorage1.Resources.Mappings.Caption = "Description";
            this.schedulerStorage1.Resources.Mappings.Id = "Id";
            this.schedulerStorage1.Resources.Mappings.ParentId = "ParentId";


            this.schedulerStorage1.AppointmentsInserted += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentsInserted);
            this.schedulerStorage1.AppointmentsChanged += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentsChanged);
            this.schedulerStorage1.AppointmentsDeleted += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentsDeleted);


            this.schedulerStorage1.AppointmentDependenciesInserted += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentDependenciesInserted);
            this.schedulerStorage1.AppointmentDependenciesChanged += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentDependenciesChanged);
            this.schedulerStorage1.AppointmentDependenciesDeleted += new DevExpress.XtraScheduler.PersistentObjectsEventHandler(this.schedulerStorage1_AppointmentDependenciesDeleted);
            // 


需要注意的一个点:ID的处理。
这个地方,devExpress网站,有一些文章作解释。
大意是说,如果使用Sqlserver,则ID不需要作处理,
但如果使用Access,则不成。

我想,这都是微软故意的,微软就是不想让程序员使用MDB,理由是显而易见的。
微软此类事情,做得太多太多。事实上,大多数应用,Access的性能就足够了。

程序员的心都被他们伤了。

真的不推荐,程序员们,与windows绑定。 有时间,还是学习其它平台的为好。

只是,学习devExpress,一方面,工作需要,另一方面,数据与UI的结合,有许多地方,不需要再自己从头开始研究。

所以,这里,不得不写了许多本不应当存在的代码

  1. this.tasksTableAdapter.Adapter.RowUpdated += new System.Data.OleDb.OleDbRowUpdatedEventHandler(tasksTableAdapter_RowUpdated);
  2. this.taskDependenciesTableAdapter.Adapter.RowUpdated += new System.Data.OleDb.OleDbRowUpdatedEventHandler(taskDependenciesTableAdapter_RowUpdated);
  3. this.resourcesTableAdapter.Adapter.RowUpdated += new System.Data.OleDb.OleDbRowUpdatedEventHandler(resourcesTableAdapter_RowUpdated);



  1. private void tasksTableAdapter_RowUpdated(object sender, System.Data.OleDb.OleDbRowUpdatedEventArgs e) {
  2. if (e.Status == UpdateStatus.Continue && e.StatementType == StatementType.Insert) {
  3. id = 0;
  4. using (OleDbCommand cmd = new OleDbCommand("SELECT @@IDENTITY", tasksTableAdapter.Connection)) {
  5. id = (int)cmd.ExecuteScalar();
  6. }
  7. e.Row["Id"] = id;
  8. }
  9. }
  10. int id2 = 0;
  11. private void taskDependenciesTableAdapter_RowUpdated(object sender, System.Data.OleDb.OleDbRowUpdatedEventArgs e) {
  12. if (e.Status == UpdateStatus.Continue && e.StatementType == StatementType.Insert) {
  13. id2 = 0;
  14. using (OleDbCommand cmd = new OleDbCommand("SELECT @@IDENTITY", taskDependenciesTableAdapter.Connection)) {
  15. id2 = (int)cmd.ExecuteScalar();
  16. }
  17. e.Row["Id"] = id2;
  18. }
  19. }
  20. int id3 = 0;
  21. private void resourcesTableAdapter_RowUpdated(object sender, System.Data.OleDb.OleDbRowUpdatedEventArgs e) {
  22. if (e.Status == UpdateStatus.Continue && e.StatementType == StatementType.Insert) {
  23. id3 = 0;
  24. using (OleDbCommand cmd = new OleDbCommand("SELECT @@IDENTITY", resourcesTableAdapter.Connection)) {
  25. id3 = (int)cmd.ExecuteScalar();
  26. }
  27. e.Row["Id"] = id3;
  28. }
  29. }


设计界面

上图,我们对比普通的Apponntment的Map来看,会发现,多出上述两个字段。




从上图,我们看到,资源自相关,是SchedulerControl自带功能,不需要我们做额外工作。


其它

左侧的资源树,如何与SchedulerControl相关联:
            this.resourcesTree1.SchedulerControl = this.schedulerControl1;

使用的场景分析

从上面的分析来看,甘特图,并不是很简单。

以自己这些年的工作经验来看,普通员工,并不喜欢这个玩意。
与本文的分析是类似的。

原因是,在输入信息时,脑子里要想的东西太多。
没有人会喜欢这样的界面。

事实上,人的大脑在这种紧张的状态下,所填的信息,往往与事实无关。比如,一个团队引入这种严格的时间管理,往往结局是坏了——你不得不投入专门人力来维护这个时间表。这只是错误的开始,最终人们会忘掉自己的用户,而面对一张毫无意义的时间表在工作。

那么,甘特图,它可以用在哪里呢?

个人看来,如果是自动生成的甘特图,看起来,还是有些意义。
也就是说,这种图形,适合用来做报表。

比如说,我目前正在进行的自动打包工作,在结束后,自动做出一个甘特图,
这样,我们就能分析出来,哪些步骤所花时间最长,便于优化与分解。

所以,这里的思想就是,用户的输入要尽可能简单,而程序返还给用户的,需要尽可能丰富。


声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号