甘特图控件DHTMLX Gantt入门使用教程【引入】:dhtmlxGantt 与 ASP.NET MVC(上)

news2024/11/15 4:53:28

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术(PHP,ASP.NET,Java等)简单集成,满足多种定制开发需求。

DHTMLX JavaScript UI 库所开发的 JavaScript 组件易于使用且功能丰富,非常适合任何领域和任何复杂性的解决方案,能够节省创建和维护业务应用程序的时间,提高生产力。

DHTMLX Gantt 最新下载(qun:764148812)icon-default.png?t=N3I4https://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享有超十年声誉,支持跨浏览器和跨平台,性价比高,可满足项目管理控件应用的所有需求,是较为完善的甘特图图表库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/505324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6. 构造函数和析构函数

一、对象的初始化和清理 C中的面向对象来源于生活&#xff0c;每个对象也都会有初始设置以及对象销毁前的清理数据的设置&#xff0c;对象的初始化和清理也是两个非常重要的安全问题 一个对象或者变量没有初始状态&#xff0c;对其使用后果是未知的使用完一个对象或变量&#x…

利用LSTM(Long Short-Term Memory)进行回归预测的原理和python代码

文章目录 一、LSTM&#xff08;Long Short-Term Memory&#xff09;是什么&#xff1f;二、使用LSTM进行回归预测时需要以下几个步骤1.数据预处理&#xff1a;2.构建LSTM模型&#xff1a;3.模型训练&#xff1a;4.模型预测&#xff1a; 三、Python实现的简单LSTM回归预测程序代…

复用,多址的区分以及其涉及的相关数据速率

复用技术 为了让尽可能多的手机使用同一个频段&#xff0c;无线通信设计了多址复用技术&#xff1a; 时分多路复用&#xff08;Time Division Multiplexing&#xff0c;TDM)要求各个子通道按时间片轮流地占用整个带宽。时间片的大小可以按一次传送一位、一个字节或一个固定大…

Hudi学习1:概述

Hudi 概念 Apache Hudi 是一个支持插入、更新、删除的增量数据湖处理框架&#xff0c;有两种表类型&#xff1a;COW和MOR&#xff0c;可以自动合并小文件&#xff0c;Hudi自己管理元数据&#xff0c;元数据目录为.hoodie。 Hudi提供表、事务、高效的追加/删除、高级索引、流接收…

【全栈第一课】微信小程序从入门到精通

微信小程序 1. 环境准备2. 小程序结构目录2.1 小程序和传统web文件结构对比2.2 基本的项目目录 3. 配置文件JSON3.1 [全局配置app.json](https://developers.weixin.qq.com/miniprogram/dev/framework/config.html)3.2 [页面配置page.json](https://developers.weixin.qq.com/m…

【标准化方法】(2) Layer Normalization 原理解析、代码复现,附Pytorch代码

大家好&#xff0c;今天和各位分享一下深度学习中常见的标准化方法&#xff0c;在 Transformer 模型中常用的 Layer Normalization&#xff0c;从数学公式的角度复现一下代码。 看本节前建议各位先看一下 Batch Normalization&#xff1a;https://blog.csdn.net/dgvv4/article…

用友携国资国企走进浙江龙游,共探区县国资智慧监管新样板

近日&#xff0c;由龙游县国有资产经营有限公司指导&#xff0c;用友网络科技股份有限公司&#xff08;以下简称&#xff1a;用友网络&#xff09;主办的“成为数智企业 迈向高质量发展——2023走进龙游数智化观摩研讨会”在浙江龙游成功举办&#xff01;全国近百位国资国企负责…

Cocos Creator 3.x 热更新,使用chatgpt快速定位解决问题

为什么要使用app热更 使用 app 热更的主要原因是可以快速地向用户推送应用程序的更新版本&#xff0c;同时也可以减少应用程序更新时需要用户手动下载和安装的次数&#xff0c;从而提高用户体验和应用程序的可维护性。以下是一些使用 app 热更的好处&#xff1a; 快速发布更新…

react初始化配置rem,less,@,本地代理,通配符,视口单位等

初始化项目之后&#xff0c;项目配置中默认配置的是scss 想用less就需要单独配置了&#xff0c;在做一个完整的项目情况下create-react-app搭出来架子的配置往往是不够的至少需要简单配置以下信息 暴露webpack之后会增加很多文件和依赖配置&#xff0c;有些时候并不想把它暴露出…

阿里云镜像区别公共镜像、自定义、共享、云市场和社区镜像介绍

阿里云服务器镜像根据来源不同分为公共镜像、自定义镜像、共享镜像、云市场镜像和社区镜像&#xff0c;一般没有特殊情况选择公共镜像&#xff0c;公共镜像是阿里云官网提供的正版授权操作系统&#xff0c;云市场镜像是在纯净版操作系统的基础上预装了相关软件及运行环境&#…

自动修改文章的软件-文章原创软件

免费版自动修改文章的软件 免费版自动修改文章的软件是一种又快速、易用且免费的文章修改软件&#xff0c;可以帮助用户批量修改文章和图文&#xff0c;并为用户提供高质量的修改服务。用户仅需上传待修改的文章文件&#xff0c;软件就能自动检测出文章中的语法、拼写错误和表…

开发人员如何理解《辟邪剑谱》的“前8个字”

辟邪剑谱可以说是武林至宝&#xff0c;人人都想得到&#xff0c;让自己冲破三流侠客的行列。得到的人&#xff0c;心里激动不已&#xff0c;得等到四下无人的时候才敢偷偷去练。但奈何最前面有8个字被折叠起来了&#xff0c;很多人也曾得到过&#xff0c;但一直没看到这前8个字…

【shell函数】

目录 一、shell函数1、shell函数的定义 二、函数传参三、阶乘四、函数实验题目 一、shell函数 使用函数可以避免代码重复 使用函数可以将大的工程分割为若干小的功能模块&#xff0c;代码的可读性更强 1、shell函数的定义 函数返回值: return表示退出函数并返回一个退出值&…

Linux | 学习笔记(适合小白)

操作系统概述&#xff1a; 计算机是由硬件和软件这两个主要部分组成的操作系统是软件的一类&#xff0c;主要作用是协助用户调度硬件工作&#xff0c;充当用户和计算机硬件之间的桥梁常见的操作系统&#xff1a;PC端&#xff1a;Windows&#xff0c;Linux&#xff0c;MacOS&…

ShardingSphere系列一(MySQL主从架构及读写分离实战(搭建主从集群、MySQL高可用方案MHA、分库分表概念))

文章目录 1. 搭建主从集群1.1 概念1.2 同步的原理1.3 搭建主从同步实战1.3.1 配置master主库1.3.2 配置slave从库1.3.3 主从集群测试 1.4 主从同步扩展1.4.1 主库同步与部分同步&#xff08;同步范围限制&#xff09;1.4.2 读写分离配置1.4.3 其他集群方式 1.5 GTID同步集群1.6…

Linux的这七大认识误区,你千万别有!

导读本文罗列了大家对Linux的七大认识误区&#xff0c;看看其中那个是你也出现过的。千万别让这些先入为主的观点断送了你体验新事物的机会。 Linux的受众群体并不大。对还是错? 错&#xff01;大错而特错。 我承认&#xff0c;Linux的实际用户数量很难统计&#xff0c;因为…

【1.JS基础-JavaScript的基本语法和数据类型】

1.JavaScript的编写方式 2 JavaScript的交互方式 3 Chrome的调试工具 4 变化数据的记录 – 变量 如果一个变量有声明&#xff0c;但是没有赋值&#xff0c;那么默认值是undefined 5 JavaScript的数据类型 typeof操作符 6 Number类型 number 类型代表整数和浮点数。 ◼ isNaN…

举一反三学python(12)—制作简易计算器

下图为简易、实用的计算器的效果图&#xff0c;今天展示用百行代码完成。 一、导入模块 import tkinter as tk 二、整体布局 win tk.Tk() # 实例化一个窗体对象 win.title(简易计算器) # 窗口标题 win.geometry(295x280) # 窗…

ESP8266图形播放器 + 天气时钟显示项目更新

<fontcolor=green>ESP8266图形播放器 + 天气时钟显示项目更新 🎞原项目播放效果演示:https://www.ixigua.com/6968269356820070912?logTag=f37e7f1f5cefa9876746✨由于有些库的更新以及API调用接口的失效,特此更新,内容上做了精简和优化。⚡由于所调用的库比较多,…

IPWorks VoIP 2022.0.8505 C++ Edition

IPWorks VoIP IPWorks VoIP 2022 C Edition 支持常见 SIP 和 IVR 操作的简单 VoIP 库。 网络语音组件 IPWorks VoIP 提供 SIP 和 IVR 组件&#xff0c;旨在促进 CTI 应用中的常见 VoIP 操作。快速集成功能&#xff0c;以根据您的自定义 IVR 菜单建立拨出呼叫、接听来电和路由呼…