### Web API Endpoints for Gantt Data in ASP.NET MVC Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt Provides RESTful API endpoints in an ASP.NET MVC controller to serve Gantt chart data (tasks, dependencies, resources, assignments). It utilizes DevExtreme's DataSourceLoader for efficient data handling. Expects HTTP GET requests and returns data in a format compatible with DevExtreme widgets. ```csharp using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using System.Net.Http; using System.Web.Http; using DevExtremeMvcApp1.Models; public class SampleDataController : ApiController { [HttpGet] public HttpResponseMessage GetTasks(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(GanttDataProvider.Tasks, loadOptions)); } [HttpGet] public HttpResponseMessage GetDependencies(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(GanttDataProvider.Dependencies, loadOptions)); } [HttpGet] public HttpResponseMessage GetResources(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(GanttDataProvider.Resources, loadOptions)); } [HttpGet] public HttpResponseMessage GetResourceAssignments(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(GanttDataProvider.ResourceAssignments, loadOptions)); } } ``` -------------------------------- ### Render Actual Task Bar (JavaScript) Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt Calculates and renders the actual task bar within the Gantt chart. This JavaScript function determines the position and width of the actual task bar based on the difference between planned and actual start and end dates, converting time differences into pixel measurements for accurate visual representation. ```javascript // Index.cshtml - Actual task positioning logic function appendActualTask(taskData, taskWidth, container) { // Calculate the total planned task range in milliseconds var taskRange = taskData.EndDate - taskData.StartDate; // Calculate pixels per millisecond var tickSize = taskWidth / taskRange; // Calculate offset of actual start from planned start var actualTaskOffset = new Date(taskData.ActualStartDate) - taskData.StartDate; // Calculate actual task duration var actualTaskRange = new Date(taskData.ActualEndDate) - new Date(taskData.ActualStartDate); // Convert time ranges to pixel measurements var actualTaskWidth = Math.round(actualTaskRange * tickSize) + "px"; var actualTaskLeftPosition = Math.round(actualTaskOffset * tickSize) + "px"; // Create the actual task bar with calculated dimensions $(document.createElement("div")) .addClass("actual-task") .attr("style", "width:" + actualTaskWidth + "; left:" + actualTaskLeftPosition) .appendTo(container); } ``` -------------------------------- ### Implement Session-Based Data Provider for Gantt Data Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt The GanttDataProvider class manages data persistence using HTTP session storage in ASP.NET. It provides static access to tasks, dependencies, resources, and resource assignments, initializing them from session if they don't exist. This C# class relies on ASP.NET's HttpContext and SessionState. ```csharp public static class GanttDataProvider { const string TasksSessionKey = "Tasks1"; const string DependenciesSessionKey = "Dependencies1"; const string ResourcesSessionKey = "Resources1"; const string ResourceAssignmentsSessionKey = "ResourceAssignments1"; static HttpSessionState Session { get { return HttpContext.Current.Session; } } public static List Tasks { get { if (Session[TasksSessionKey] == null) Session[TasksSessionKey] = CreateTasks(); return (List)Session[TasksSessionKey]; } } static List CreateTasks() { var result = new List(); result.Add(CreateTask("0", "-1", "Software Development", "02/21/2021 08:00:00", "03/15/2021 15:00:00", "02/21/2021 08:00:00", "03/25/2021 12:00:00", "31", "1", "0", "", "")); // ... more tasks return result; } } ``` -------------------------------- ### Configure DevExtreme Gantt Widget (C#) Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt Configures the DevExtreme Gantt widget using C# helper methods within a .NET MVC application. It binds data sources for tasks, dependencies, resources, and resource assignments, and defines essential task properties like key, title, start/end dates, and parent relationships. It also specifies column configurations and the scale type. ```cshtml @using DevExtremeMvcApp1.Models @(Html.DevExtreme().Gantt() .ID("gantt") .RootValue("-1") .Tasks(t => t .DataSource(d => d.WebApi().Controller("SampleData").Key("Key").LoadAction("GetTasks")) .KeyExpr("Key") .TitleExpr("Title") .ParentIdExpr("ParentKey") .StartExpr("StartDate") .EndExpr("EndDate") .ProgressExpr("Progress") ) .Dependencies(dep => dep .DataSource(d => d.WebApi().Controller("SampleData").Key("Key").LoadAction("GetDependencies")) .KeyExpr("Key") .PredecessorIdExpr("PredecessorKey") .SuccessorIdExpr("SuccessorKey") ) .Resources(r => r .DataSource(d => d.WebApi().Controller("SampleData").Key("Key").LoadAction("GetResources")) .KeyExpr("Key") .TextExpr("Name") ) .ResourceAssignments(ra => ra .DataSource(d => d.WebApi().Controller("SampleData").Key("Key").LoadAction("GetResourceAssignments")) .KeyExpr("Key") .TaskIdExpr("TaskKey") .ResourceIdExpr("ResourceKey") ) .Columns(columns => { columns.AddFor(m => m.Title).Caption("Title").Width(150); columns.AddFor(m => m.StartDate).Visible(false); columns.AddFor(m => m.ActualStartDate).Visible(false); columns.AddFor(m => m.EndDate).Visible(false); columns.AddFor(m => m.ActualEndDate).Visible(false); columns.AddFor(m => m.Progress).Visible(false); }) .TaskContentTemplate(new JS("getTaskContentTemplate")) .ScaleType(GanttScaleType.Days) .TaskListWidth(400) ) ``` -------------------------------- ### Generate Dependencies from Task Relationships in C# Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt This C# code demonstrates how to automatically generate task dependencies based on parent-child relationships within the Gantt chart data. It iterates through tasks and creates predecessor-successor links, ensuring proper task sequencing. It utilizes a helper method `CreateUniqueId` for generating unique keys. ```csharp public class Dependency { public string Key { get; set; } public string PredecessorKey { get; set; } public string SuccessorKey { get; set; } } static List CreateDependencies() { var result = new List(); for (int i = 0; i < Tasks.Count; i++) { Task task = Tasks[i]; if (!string.IsNullOrEmpty(task.ParentKey) && (task.ParentKey != "-1")) { // Link each task to its previous sibling as a dependency result.Add(new Dependency() { Key = CreateUniqueId(), PredecessorKey = Tasks[i - 1].Key, SuccessorKey = task.Key }); } } return result; } static string CreateUniqueId() { return Guid.NewGuid().ToString(); } ``` -------------------------------- ### Define Resource and Resource Assignment Models in C# Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt These C# models define the structure for resources (e.g., team members, roles) and resource assignments, which link resources to specific tasks. The `ResourceAssignment` model uses a comma-separated string of resource IDs from the `Task` model. These models are part of the data management for the Gantt chart. ```csharp public class Resource { public string Key { get; set; } public string Name { get; set; } } public class ResourceAssignment { public string Key { get; set; } public string TaskKey { get; set; } public string ResourceKey { get; set; } } static List CreateResources() { var result = new List(); result.Add(new Resource() { Key = "1", Name = "Management" }); result.Add(new Resource() { Key = "2", Name = "Project Manager" }); result.Add(new Resource() { Key = "3", Name = "Analyst" }); result.Add(new Resource() { Key = "4", Name = "Developer" }); result.Add(new Resource() { Key = "5", Name = "Testers" }); return result; } static List CreateResourceAssignments() { var result = new List(); foreach (Task task in Tasks) { if (!string.IsNullOrEmpty(task.Resources)) { string[] resourcesID = task.Resources.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries ); for (int i = 0; i < resourcesID.Length; i++) { result.Add(new ResourceAssignment() { Key = CreateUniqueId(), TaskKey = task.Key, ResourceKey = resourcesID[i] }); } } } return result; } ``` -------------------------------- ### Task Data Model for Dual Timeline Gantt Chart Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt Defines a Task model in C# that includes properties for both planned (StartDate, EndDate) and actual (ActualStartDate, ActualEndDate) task timelines. This model is used to populate the Gantt chart data, enabling the visualization of deviations between planned and actual progress. The model also includes fields for key, parent key, title, description, progress, and resources. ```csharp using System; using System.Collections.Generic; public class Task { public string Key { get; set; } public string ParentKey { get; set; } public string Title { get; set; } public string Description { get; set; } public DateTime StartDate { get; set; } // Planned start public DateTime EndDate { get; set; } // Planned end public DateTime ActualStartDate { get; set; } // Actual start public DateTime ActualEndDate { get; set; } // Actual end public int Progress { get; set; } public string Resources { get; set; } } // Example of creating a task with dual timeline data: var tasks = new List(); tasks.Add(CreateTask( key: "2", parentkey: "1", title: "Determine project scope", start: "02/22/2021 08:00:00", // Planned dates end: "02/24/2021 12:00:00", actualstart: "02/24/2021 00:00:00", // Actual dates (delayed) actualEnd: "02/28/2021 00:00:00", percent: "100", type: "1", status: "2", resources: "1", description: "Important" )); ``` -------------------------------- ### Custom Task Content Template (JavaScript) Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt Defines a JavaScript function to render custom content for each task in the Gantt widget. This template is responsible for creating the visual elements that represent both the planned and actual timelines for a task by calling helper functions to append the respective task bars. ```javascript // Index.cshtml - JavaScript functions function getTaskContentTemplate(item) { var $parentContainer = $(document.createElement("div")); appendPlannedTask(item.taskData, item.taskResources[0], item.taskSize.width, $parentContainer); appendActualTask(item.taskData, item.taskSize.width, $parentContainer); return $parentContainer; } function appendPlannedTask(taskData, resource, taskWidth, container) { var $plannedTaskContainer = $(document.createElement("div")) .addClass("planned-task") .attr("style", "width:" + taskWidth + "px;") .appendTo(container); var $wrapper = $(document.createElement("div")) .addClass("planned-task-wrapper") .appendTo($plannedTaskContainer); $(document.createElement("div")) .addClass("planned-task-title") .text(taskData.Title) .appendTo($wrapper); $(document.createElement("div")) .addClass("planned-task-resource") .text(resource ? resource.text : "") .appendTo($wrapper); $(document.createElement("div")) .addClass("planned-task-progress") .attr("style", "width:" + (parseFloat(taskData.Progress)) + "%;") .appendTo($plannedTaskContainer); } ``` -------------------------------- ### Configure Planned and Actual Task Styling with CSS Source: https://context7.com/devexpress-examples/devextreme-gantt-planned-vs-actual-tasks/llms.txt CSS styles are used to visually differentiate planned and actual task bars in the DevExtreme Gantt chart. These styles define properties like background color, opacity, borders, and text appearance for various task elements. No external dependencies are required beyond standard CSS. ```css #gantt { height: 700px; } .dx-gantt .dx-row { height: 63px; } .actual-task { height: 100%; display: inline-block; overflow: hidden; position: absolute; background-color: #92c3f2; opacity: 0.5; border-radius: 3px; } .planned-task { max-height: 48px; height: 100%; display: inline-block; overflow: hidden; border-radius: 3px 3px 0px 0px; background-color: #5C57C9; } .planned-task-wrapper { padding: 8px; color: #fff; } .planned-task-title { font-weight: 600; font-size: 13px; } .planned-task-resource { font-size: 12px; } .planned-task-progress { position: absolute; left: 0; bottom: 0; width: 0%; height: 4px; background: rgba(0, 0, 0, .5); border-radius: 0px 0px 0px 3px; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.