DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术(PHP,ASP.NET,Java等)简单集成,满足多种定制开发需求。
DHTMLX JavaScript UI 库所开发的 JavaScript 组件易于使用且功能丰富,非常适合任何领域和任何复杂性的解决方案,能够节省创建和维护业务应用程序的时间,提高生产力。
DHTMLX Gantt 最新下载(qun:764148812)https://www.evget.com/product/4213/download
本教程将为您提供有关在服务器端使用 ASP.NET 和 REST API 创建甘特图的分步说明。
我们将利用 ASP.NET MVC 5 Web 平台和用于 REST API API 的 Web API 2 控制器来创建甘特图应用程序。 为了组织与数据库的通信,我们将使用实体框架。 我们将在Visual Studio IDE的帮助下构建我们的应用程序。
第 1 步:创建项目
创建新的 Visual Studio 项目
启动 Visual Studio 2022,然后选择“创建新项目”。
接下来选择“ASP.NET Web 应用程序”并将其命名为 DHX。如果找不到必要的模板,请查看故障排除部分。
在可用模板中选择一个空项目,然后选中模板列表附近的 MVC 和 Web API 复选框。
第2步:将甘特图添加到页面
创建控制器
现在我们有一个空项目,一切都准备好实施我们的甘特图。
首先,我们将添加一个 MVC 控制器,它将显示一个带有甘特图的页面。
若要创建它,请调用“控制器”文件夹的上下文菜单,然后选择“加载项->控制器”。 在打开的窗口中,选择 MVC 5 控制器 -> 空,并将新添加的控制器命名为“HomeController”。
HomeController 默认具有 ActionResult 类的 Index() 方法,因此它不需要任何其他逻辑。我们将为它添加一个视图。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace DHX.Gantt.Web.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } } }
创建视图
现在是时候创建我们的索引页了。转到“视图/主页”并添加一个名为“索引”的空视图:
打开新创建的视图并将以下代码放入其中:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <link href="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" rel="stylesheet" type="text/css" /> <script src="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script> <script> document.addEventListener("DOMContentLoaded", function(event) { // specifying the date format gantt.config.date_format = "%Y-%m-%d %H:%i"; // initializing gantt gantt.init("gantt_here"); // initiating data loading gantt.load("/api/data"); // initializing dataProcessor var dp = new gantt.dataProcessor("/api/"); // and attaching it to gantt dp.init(gantt); // setting the REST mode for dataProcessor dp.setTransactionMode("REST"); }); </script> </head> <body> <div id="gantt_here" style="width: 100%; height: 100vh;"></div> </body> </html>
我们在这一步做了什么:
- 为我们的甘特图应用程序定义了一个简单的页面标记
- 添加了使用 CDN 链接的 DHTMLX 甘特 JS/CSS 源
- 并在页面上创建了甘特图
请注意配置:我们已指定来自数据源的日期格式。
gantt.config.date_format = "%Y-%m-%d %H:%i";
我们的客户端需要能够解析来自服务器的日期。
我们还告诉甘特图,它将在后端与 RESTful API 一起使用,并使用“/api/”作为默认路由:
gantt.load("/api/data"); // initializing dataProcessor var dp = new gantt.dataProcessor("/api/"); // and attaching it to gantt dp.init(gantt); // setting the REST mode for dataProcessor dp.setTransactionMode("REST");
服务器端本身将在稍后实现。现在,您可以运行应用程序并查看甘特图在页面上呈现。
第3步:创建模型和数据库
创建模型
现在我们应该为甘特图定义模型类。甘特图数据模型由链接和任务组成。 如您所见,dhtmlxGantt 对数据模型使用某种命名约定,该约定不同于 C# 中传统上使用的命名约定。 客户端模型还可以包含一些不需要存储在数据库中但将在客户端或后端逻辑中使用的属性。
因此,我们将在此处使用数据传输对象模式:我们将定义将与 EF 一起使用并在应用内部使用的域模型类,以及将用于与 Web API 通信的 DTO 类。然后,我们将在两个模型之间实现某种映射。
让我们开始吧!
任务模型
首先,我们将为 Task 创建一个类。它的内容可以类似于这个:
using System; namespace DHX.Gantt.Web.Models { public class Task { public int Id { get; set; } public string Text { get; set; } public DateTime StartDate { get; set; } public int Duration { get; set; } public decimal Progress { get; set; } public int? ParentId { get; set; } public string Type { get; set; } } }
您可以在相应的文档文章中找到可用于 Task 对象的完整属性列表(必需属性和可选属性)。
链接模型
现在是 Link 类的时候了,它可能如下所示:
namespace DHX.Gantt.Web.Models { public class Link { public int Id { get; set; } public string Type { get; set; } public int SourceTaskId { get; set; } public int TargetTaskId { get; set; } } }
配置数据库连接
安装实体框架
您还记得,我们将在实体框架的帮助下使用数据库组织工作。
因此,首先我们需要安装框架。为此,您需要在程序包管理器控制台中运行以下命令:
Install-Package EntityFramework
创建数据库上下文
下一步是创建上下文。上下文表示与数据库的会话。它允许获取和保存数据。
调用“模型”文件夹的上下文菜单,然后选择“添加类>类”。新类将称为“甘特上下文”,并将具有以下内容:
using System.Data.Entity; namespace DHX.Gantt.Web.Models { public class GanttContext : DbContext { public DbSet<Task> Tasks { get; set; } public DbSet<Link> Links { get; set; } } }
将初始记录添加到数据库
现在我们可以将一些记录添加到数据库中。
实体框架可以在应用程序运行时自动创建数据库。 我们应该指定每当模型更改时都应删除并重新创建数据库。
首先,我们应该创建一个数据库初始值设定项。为此,我们需要在 App_Start 文件夹中添加一个新类 它将继承自 DropCreateDatabaseIfModelChanges 类。我们称之为“甘特初始值设定项”。
在此类中,我们将重新定义 Seed() 方法以用测试数据填充它。然后,我们将使用 Add() 方法将实体集合添加到上下文中。
甘特初始值设定项类的完整代码如下:
using System; using System.Collections.Generic; using System.Data.Entity; namespace DHX.Gantt.Web.Models { public class GanttInitializer : DropCreateDatabaseIfModelChanges<GanttContext> { protected override void Seed(GanttContext context) { List<Task> tasks = new List<Task>() { new Task() { Id = 1, Text = "Project #2", StartDate = DateTime.Today.AddDays(-3), Duration = 18, Progress = 0.4m, ParentId = null }, new Task() { Id = 2, Text = "Task #1", StartDate = DateTime.Today.AddDays(-2), Duration = 8, Progress = 0.6m, ParentId = 1 }, new Task() { Id = 3, Text = "Task #2", StartDate = DateTime.Today.AddDays(-1), Duration = 8, Progress = 0.6m, ParentId = 1 } }; tasks.ForEach(s => context.Tasks.Add(s)); context.SaveChanges(); List<Link> links = new List<Link>() { new Link() {Id = 1, SourceTaskId = 1, TargetTaskId = 2, Type = "1"}, new Link() {Id = 2, SourceTaskId = 2, TargetTaskId = 3, Type = "0"} }; links.ForEach(s => context.Links.Add(s)); context.SaveChanges(); } } } 打开 Global.asax 文件。它包含在
应用程序启动时运行的代码。 将必要的命名空间和将为上下文设置初始值设定项的代码行添加到 Application_Start() 方法中:
using System; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Web.Http; using System.Data.Entity; using DHX.Gantt.Web.Models; namespace DHX.Gantt.Web { public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { // Code that runs on application startup AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); RouteConfig.RegisterRoutes(RouteTable.Routes); Database.SetInitializer(new GanttInitializer()); } } }
定义 DTO 和映射
是时候声明将用于 Web API 的 DTO 类了。 至于模型和 DTO 之间的映射,我们将采用最简单的方法,只为这些类定义一个显式转换运算符。
TaskDto 类将如下所示:
using System; namespace DHX.Gantt.Web.Models { public class TaskDto { public int id { get; set; } public string text { get; set; } public string start_date { get; set; } public int duration { get; set; } public decimal progress { get; set; } public int? parent { get; set; } public string type { get; set; } public bool open { get { return true; } set { } } public static explicit operator TaskDto(Task task) { return new TaskDto { id = task.Id, text = task.Text, start_date = task.StartDate.ToString("yyyy-MM-dd HH:mm"), duration = task.Duration, parent = task.ParentId, type = task.Type, progress = task.Progress }; } public static explicit operator Task(TaskDto task) { return new Task { Id = task.id, Text = task.text, StartDate = DateTime.Parse( task.start_date, System.Globalization.CultureInfo.InvariantCulture), Duration = task.duration, ParentId = task.parent, Type = task.type, Progress = task.progress }; } } }
LinkDto 类的代码如下:
namespace DHX.Gantt.Web.Models { public class LinkDto { public int id { get; set; } public string type { get; set; } public int source { get; set; } public int target { get; set; } public static explicit operator LinkDto(Link link) { return new LinkDto { id = link.Id, type = link.Type, source = link.SourceTaskId, target = link.TargetTaskId }; } public static explicit operator Link(LinkDto link) { return new Link { Id = link.id, Type = link.type, SourceTaskId = link.source, TargetTaskId = link.target }; } } }
最后,让我们为数据源添加一个模型:
using System.Collections.Generic; namespace DHX.Gantt.Web.Models { public class GanttDto { public IEnumerable<TaskDto> data { get; set; } public IEnumerable<LinkDto> links { get; set; } } }
第 4 步:实现网络应用程序接口
使用 REST API 加载数据的一般技术
最后是时候实现 API 了。
从 API 详细信息中可以看到,我们需要两个控制器:一个用于任务,一个用于链接。 我们还需要一个控制器来执行“加载数据”操作,因为甘特图预计那里的结果会好坏参半。
任务控制器
要创建新控制器:
- 激活“控制器”文件夹的上下文菜单,然后选择“添加 ->控制器”。
- 选择 Web API 2 控制器 ->为空。新控制器将称为“任务控制器”。
现在我们需要为任务条目实现基本的 CRUD 操作:
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web.Http; using System.Web.UI.WebControls; using DHX.Gantt.Web.Models; namespace DHX.Gantt.Web.Controllers { public class TaskController : ApiController { private GanttContext db = new GanttContext(); // GET api/Task public IEnumerable<TaskDto> Get() { return db.Tasks .ToList() .Select(t => (TaskDto)t); } // GET api/Task/5 [System.Web.Http.HttpGet] public TaskDto Get(int id) { return (TaskDto)db .Tasks .Find(id); } // PUT api/Task/5 [System.Web.Http.HttpPut] public IHttpActionResult EditTask(int id, TaskDto taskDto) { var updatedTask = (Task)taskDto; updatedTask.Id = id; db.Entry(updatedTask).State = EntityState.Modified; db.SaveChanges(); return Ok(new { action = "updated" }); } // POST api/Task [System.Web.Http.HttpPost] public IHttpActionResult CreateTask(TaskDto taskDto) { var newTask = (Task)taskDto; db.Tasks.Add(newTask); db.SaveChanges(); return Ok(new { tid = newTask.Id, action = "inserted" }); } // DELETE api/Task/5 [System.Web.Http.HttpDelete] public IHttpActionResult DeleteTask(int id) { var task = db.Tasks.Find(id); if (task != null) { db.Tasks.Remove(task); db.SaveChanges(); } return Ok(new { action = "deleted" }); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } } }
这里的一切都非常简单:
- 在GET操作中,我们从数据库加载任务并输出其数据传输对象
- 在 PUT/POST 操作中,我们将 DTO 作为输入,将其转换为任务模型并将更改保存到数据库上下文中
现在让我们对链接做同样的事情。
链路控制器
我们将为如下所示的链接创建一个空的 Web API 控制器:
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web.Http; using DHX.Gantt.Web.Models; namespace DHX.Gantt.Web.Controllers { public class LinkController : ApiController { private GanttContext db = new GanttContext(); // GET api/Link [System.Web.Http.HttpGet] public IEnumerable<LinkDto> Get() { return db .Links .ToList() .Select(l => (LinkDto)l); } // GET api/Link/5 [System.Web.Http.HttpGet] public LinkDto Get(int id) { return (LinkDto)db .Links .Find(id); } // POST api/Link [System.Web.Http.HttpPost] public IHttpActionResult CreateLink(LinkDto linkDto) { var newLink = (Link)linkDto; db.Links.Add(newLink); db.SaveChanges(); return Ok(new { tid = newLink.Id, action = "inserted" }); } // PUT api/Link/5 [System.Web.Http.HttpPut] public IHttpActionResult EditLink(int id, LinkDto linkDto) { var clientLink = (Link)linkDto; clientLink.Id = id; db.Entry(clientLink).State = EntityState.Modified; db.SaveChanges(); return Ok(new { action = "updated" }); } // DELETE api/Link/5 [System.Web.Http.HttpDelete] public IHttpActionResult DeleteLink(int id) { var link = db.Links.Find(id); if (link != null) { db.Links.Remove(link); db.SaveChanges(); } return Ok(new { action = "deleted" }); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } } }
数据控制者
最后,我们将为数据操作添加一个控制器:
using System.Web.Http; using DHX.Gantt.Web.Models; namespace DHX.Gantt.Web.Controllers { public class DataController : ApiController { // GET api/ [System.Web.Http.HttpGet] public GanttDto Get() { return new GanttDto { data = new TaskController().Get(), links = new LinkController().Get() }; } } }
现在一切都准备好了。运行应用程序,页面上应出现一个成熟的甘特图:
DHTMLX Gantt享有超十年声誉,支持跨浏览器和跨平台,性价比高,可满足项目管理控件应用的所有需求,是较为完善的甘特图图表库。