This is a migrated thread and some comments may be shown as answers.

Populating Gantt with custom Provider

12 Answers 230 Views
Gantt
This is a migrated thread and some comments may be shown as answers.
David
Top achievements
Rank 1
David asked on 03 Jul 2015, 12:46 PM

As shown in the examples I have implemented a Provider for the Gantt chart. The provider appears to be working, when I break through it the methods are called, items are inserted, updated and deleted in the database etc. Both GetTasks and GetDependencies return an ITask list. The problem I'm having is that nothing appears in the Gantt chart (it loads with no Tasks showing). 
When I add new Tasks those will show (and are added to the database) and I can update them etc. After a page refresh they also no longer show.

Here is the provider implementation, GetById returns a DataSet and Mutate returns an object containing the ID of inserted item + success/error info:

public class GanttCustomProvider : GanttProviderBase
    {
        private long _projectId;
        private string _connString;
 
        public GanttCustomProvider(long projectId, string connString) : base()
        {
            _projectId = projectId;
            _connString = connString;
        }
 
        public override ITaskFactory TaskFactory
        {
            get
            {
                return new CustomGanttTaskFactory();
            }
        }
 
        public override List<ITask> GetTasks()
        {
            using (var client = new FunctionsClient())
            {
                var source = client.GetById(new Phase { PROJECT_ID = _projectId, ConnectionString = _connString })
                    .Tables[0].AsEnumerable();
 
                var list = source.Select(row => new CustomTask
                {
                    ID = row["ID"],
                    ParentID = row["PARENT"],
                    Title = row["TITLE"].ToString(),
                    Start = (DateTime)row["START_DATE"],
                    End = (DateTime)row["END_DATE"],
                    Summary = (bool)row["SUMMERY"],
                    OrderID = row["ORDER_ID"],
                    Expanded = (bool)row["EXPANDED"],
                    PercentComplete = Decimal.Parse(row["PERCENTCOMPLETE"].ToString()),
                    Time = (double)row["TIME"]
                }).ToList<ITask>();
                return list;
            }
        }
 
        public override ITask InsertTask(ITask t)
        {
            var task = (CustomTask)t;
            using (var client = new FunctionsClient())
            {
                task.ID = client.Mutate(new Phase
                {
                    PROJECT_ID = _projectId,
                    PARENT = (int?)task.ParentID,
                    TITLE = task.Title,
                    START_DATE = task.Start,
                    END_DATE = task.End,
                    SUMMERY = task.Summary,
                    ORDER_ID = (int?)task.OrderID,
                    EXPANDED = task.Expanded,
                    Mode = Modes.Insert,
                    ConnectionString = _connString
                }).returnID;
                return task;
            }
        }
 
        public override ITask UpdateTask(ITask t)
        {
            var task = (CustomTask)t;
            using(var client = new FunctionsClient())
            {
                client.Mutate(new Phase
                {
                    ID = (int)task.ID,
                    PARENT = (int?)task.ParentID,
                    PROJECT_ID = _projectId,
                    TITLE = task.Title,
                    START_DATE = task.Start,
                    END_DATE = task.End,
                    SUMMERY = task.Summary,
                    ORDER_ID = (int)task.OrderID,
                    EXPANDED = task.Expanded,
                    TIME = task.Time,
                    Mode = Modes.Update,
                    ConnectionString = _connString
                });
            }
            return task;
        }
 
        public override ITask DeleteTask(ITask task)
        {
            using (var client = new FunctionsClient())
            {
                client.Mutate(new Phase
                {
                    ID = (int)task.ID,
                    Mode = Modes.Delete,
                    ConnectionString = _connString
                });
 
                return task;
            }
        }
 
        public override List<IDependency> GetDependencies()
        {
            using (var client = new FunctionsClient())
            {
                var source = client.GetById(new PhaseDependency { ProjectID = _projectId, ConnectionString = _connString })
                    .Tables[0].AsEnumerable();
 
                var list = source.Select(row => new Dependency
                {
                    ID = row["ID"],
                    PredecessorID = row["PredecessorID"],
                    SuccessorID = row["SuccessorID"],
                    Type = (DependencyType)row["Type"]
                }).ToList<IDependency>();
                return list;
            }
        }
 
        public override IDependency InsertDependency(IDependency dependency)
        {
            using (var client = new FunctionsClient())
            {
                dependency.ID = client.Mutate(new PhaseDependency
                {
                    PredecessorID = (int)dependency.PredecessorID,
                    SuccessorID = (int)dependency.SuccessorID,
                    Type = (int)dependency.Type,
                    Mode = Modes.Insert,
                    ConnectionString = _connString
                }).returnID;
            }
            return dependency;
        }
 
        public override IDependency DeleteDependency(IDependency dependency)
        {
            using(var client = new FunctionsClient())
            {
                client.Mutate(new PhaseDependency
                {
                    ID = (int)dependency.ID,
                    Mode = Modes.Delete,
                    ConnectionString = _connString
                });
            }
            return dependency;
        }
 
}

Here are the implementations of the Custom Task and Factory:

 

public class CustomTask : Task
    {
        public CustomTask() : base() { }
 
        public double? Time
        {
            get { return (double?)(ViewState["Time"] ?? (double?)null); }
            set { ViewState["Time"] = value; }
        }
 
        protected override IDictionary<string, object> GetSerializationData()
        {
            var dict = base.GetSerializationData();
            dict["Time"] = Time;
 
            return dict;
        }
 
        public override void LoadFromDictionary(System.Collections.IDictionary values)
        {
            base.LoadFromDictionary(values);
 
            Time = values["Time"] == null ? (float?)null : float.Parse(values["Time"].ToString());
        }
    }
 
    public class CustomGanttTaskFactory : ITaskFactory
    {
        Task ITaskFactory.CreateTask()
        {
            return new CustomTask();
        }
    }

 

And finally the Page the Gantt is on:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GanttTest.aspx.cs" Inherits="GanttTest" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <telerik:RadScriptManager runat="server" />
 
        <telerik:RadGantt runat="server" id="rgPlanning"  AutoGenerateColumns="false" >
            <YearView UserSelectable="True" />
            <Columns>
                <telerik:GanttBoundColumn DataField="Title" DataType="String" Width="100px" HeaderText="Title"/>
                <telerik:GanttBoundColumn DataField="Start" DataType="DateTime" DataFormatString="dd/MM/yy" Width="100px" HeaderText="Start"/>
                <telerik:GanttBoundColumn DataField="End" DataType="DateTime" DataFormatString="dd/MM/yy" Width="100px" HeaderText="End"/>
                <telerik:GanttBoundColumn DataField="Time" DataType="Number" Width="100px" UniqueName="Time" HeaderText="Hours"/>
            </Columns>
                 
            <CustomTaskFields>
                <telerik:GanttCustomField PropertyName="Time" Type="Number" ClientPropertyName="time"/>
            </CustomTaskFields>
        </telerik:RadGantt>
    </div>
    </form>
</body>
</html>

And code behind:

    public partial class GanttTest : Page
    {
        private long? projectID = 3;
        private string connString = "Connectionstring";
 
        protected void Page_Load(object sender, EventArgs e)
        {
            rgPlanning.Provider = new GanttCustomProvider(projectID.Value, connString);
        }
    }

12 Answers, 1 is accepted

Sort by
0
David
Top achievements
Rank 1
answered on 03 Jul 2015, 12:51 PM

In the OP I said: Both GetTasks and GetDependencies return an ITask list.
I omeant that GetTasks returns an ITask list and GetDependencies returns an IDependency list.

0
Bozhidar
Telerik team
answered on 08 Jul 2015, 06:47 AM
Hello,

Could you paste in the PageSource of the loaded page, more specifically the $create statement for the gantt control. This is done by right-clicking on the page and selecting "View Page Source". Then near the bottom there should be a definition starting with:
WebForm_InitCallback();Sys.Application.add_init(function() {
    $create(Telerik.Web.UI.RadGantt,
    ...

We only need this full statement, not the whole page source.

Could you also verify that there aren't any javascript errors on the page?

Regards,
Bozhidar
Telerik
0
David
Top achievements
Rank 1
answered on 08 Jul 2015, 07:16 AM

Here is the $create statement:

WebForm_InitCallback();Sys.Application.add_init(function() {
    $create(Telerik.Web.UI.RadGantt, {"_skin":"Silk","_uniqueId":"rgPlanning","clientStateFieldID":"rgPlanning_ClientState","columnsData":[{"title":"Title","width":100,"field":"title"},{"title":"Start","width":100,"format":"{0:dd/MM/yy}","field":"start"},{"title":"End","width":100,"format":"{0:dd/MM/yy}","field":"end"},{"title":"Hours","width":100,"field":"time"}],"customTaskFields":[{"propertyName":"Time","clientPropertyName":"time","defaultValue":null,"type":2}],"dependenciesData":[{"ID":10,"PredecessorID":124,"SuccessorID":129,"Type":1},{"ID":10,"PredecessorID":124,"SuccessorID":129,"Type":1},{"ID":11,"PredecessorID":124,"SuccessorID":141,"Type":1},{"ID":11,"PredecessorID":124,"SuccessorID":141,"Type":1}],"viewsData":[{"selected":true,"type":"day"},{"type":"week"},{"monthHeaderTemplate":"#=kendo.toString(start, \u0027MMM, yyyy\u0027)#","type":"month"},{"type":"year"}]}, null, null, $get("rgPlanning"));
});

 I'm not getting any javascript errors.

0
David
Top achievements
Rank 1
answered on 08 Jul 2015, 07:18 AM
FunctionsClient is a reference to a WCF service if that is of any help.
0
Accepted
Bozhidar
Telerik team
answered on 10 Jul 2015, 08:18 AM
Hi,

The sent code indicates that on the server no Tasks are populated in the Gantt control. This can be caused by a couple of reasons:
1. No tasks are returned from the GetTasks method.
2. The returned tasks don't contain any root tasks. In the returned task collection there should be at least one root task (the ParentID property should be null).

You can check in the code behind whether the tasks are populated with the following code:
RadGantt1.DataBind();
var tasksCount = RadGantt1.Tasks.Count;


Regards,
Bozhidar
Telerik
0
David
Top achievements
Rank 1
answered on 20 Jul 2015, 09:05 AM

Thank you very much, I found the the problem. 

I double checked the Tasks being returned from the GetTasks method and apparently the database ​was retun ParentId as an empty object (perhaps DbNull) instead of null. Changing the GetTasks method to this fixed it:

public override List<ITask> GetTasks()
        {
            using (var client = new FunctionsClient())
            {
                var source = client.GetById(new Phase { PROJECT_ID = _projectId, ConnectionString = _connString })
                    .Tables[0].AsEnumerable();
                int pidOut;
 
                var list = source.Select(row => new CustomTask
                {
                    ID = row["ID"],
                    ParentID = int.TryParse(row["PARENT"].ToString(), out pidOut) ? pidOut : (int?)null,
                    Title = row["TITLE"].ToString(),
                    Start = (DateTime)row["START_DATE"],
                    End = (DateTime)row["END_DATE"],
                    Summary = (bool)row["SUMMERY"],
                    OrderID = row["ORDER_ID"],
                    Expanded = (bool)row["EXPANDED"],
                    PercentComplete = decimal.Parse(row["PERCENTCOMPLETE"].ToString()),
                    Time = (double)row["TIME"]
                }).ToList<ITask>();
                return list;
            }
        }

I had another quick question, is it possible to disable manually setting the % complete and change the unit type of resources from % to amount (or hide the unit column entirely)?

0
Bozhidar
Telerik team
answered on 20 Jul 2015, 10:00 AM
Hi,

Since this issue is resolved, I would like to ask you to post a separate forum thread for other issues, not related to this topic. That way when other people find this thread they can quickly see the solution, without going through a long and convoluted thread.

Regards,
Bozhidar
Telerik
0
Sam
Top achievements
Rank 1
answered on 08 Jul 2016, 03:09 PM

Hi I am having a similar issue where tasks are not returned in the $create statement. However, I have verified the tasks are being returned in GetTasks and RadGantt1.Tasks.Count. Would there be another reason for this? My code is below:

 

        Public Class GanttCustomProvider

            Inherits GanttProviderBase

            Private objDB As New DBGlobals

            Private iJobPhaseID As Integer

            Public Overrides ReadOnly Property TaskFactory As Telerik.Web.UI.Gantt.ITaskFactory
                Get
                    Return New MZGanttTaskFactory
                End Get
            End Property

            Public Sub New(JobPhaseID As Integer)
                MyBase.New()
                iJobPhaseID = JobPhaseID
            End Sub

            Public Overrides Function GetTasks() As List(Of Gantt.ITask)
                Dim cmd As New SqlClient.SqlCommand("JobTimelines_Get")
                cmd.CommandType = CommandType.StoredProcedure
                cmd.Parameters.Add("@TimelinePhaseID", SqlDbType.Int).Value = objDB.DBSetInt(iJobPhaseID)
                Dim dt As DataTable = objDB.GetData(cmd)
                Dim lstTasks = New List(Of Gantt.ITask)
                Dim qryTasks = dt.AsEnumerable().Select(Function(task) New MZTask() With { _
                                                        .ID = task("TimelineTaskID"), _
                                                        .ParentID = task("ParentID"), _
                                                        .Title = task("Title"), _
                                                        .Start = task("Start"), _
                                                        .End = task("End"), _
                                                        .Summary = task("Summary"), _
                                                        .OrderID = task("OrderID"), _
                                                        .Expanded = False, _
                                                        .PercentComplete = task("PercentComplete"), _
                                                        .TaskDuration = task("TaskDuration"), _
                                                        .TaskDurationRemaining = task("TaskDurationRemaining")
                                                    })
                lstTasks.AddRange(qryTasks)
                Return lstTasks
            End Function

            Public Overrides Function DeleteTask(task As Gantt.ITask) As Gantt.ITask
                Return task
            End Function

            Public Overrides Function InsertTask(task As Gantt.ITask) As Gantt.ITask
                Return task
            End Function

            Public Overrides Function UpdateTask(task As Gantt.ITask) As Gantt.ITask
                Return task
            End Function

            Public Overrides Function GetDependencies() As List(Of Gantt.IDependency)
                Dim cmd As New SqlClient.SqlCommand("SELECT * FROM ptJobTimelineDependencies WHERE TimelinePhaseID = @TimelinePhaseID")
                cmd.Parameters.Add("@TimelinePhaseID", SqlDbType.Int).Value = objDB.DBSetInt(iJobPhaseID)
                Dim dt As DataTable = objDB.GetData(cmd)
                Dim lst = New List(Of Gantt.IDependency)
                Dim qryTasks = dt.AsEnumerable().Select(Function(task) New Gantt.Dependency() With { _
                                                        .ID = task("TimelineDependencyID"), _
                                                        .Type = task("Type"), _
                                                        .PredecessorID = task("PredecessorID"), _
                                                        .SuccessorID = task("SuccessorID") _
                                                    })
                lst.AddRange(qryTasks)
                Return lst
            End Function

            Public Overrides Function DeleteDependency(dependency As Gantt.IDependency) As Gantt.IDependency
                Return MyBase.DeleteDependency(dependency)
            End Function

            Public Overrides Function InsertDependency(dependency As Gantt.IDependency) As Gantt.IDependency
                Return MyBase.InsertDependency(dependency)
            End Function

            Public Overrides Function UpdateDependency(dependency As Gantt.IDependency) As Gantt.IDependency
                Return MyBase.UpdateDependency(dependency)
            End Function

            Public Overrides Function GetAssignments() As List(Of Gantt.IAssignment)
                Dim cmd As New SqlClient.SqlCommand(
                    "SELECT ptJobTimelineTaskUsers.* " _
                    & " FROM ptJobTimelineTaskUsers INNER JOIN ptJobTimelineTasks ON ptJobTimelineTaskUsers.TimelineTaskID = ptJobTimelineTasks.TimelineTaskID " _
                    & " WHERE ptJobTimelineTasks.TimelinePhaseID = @TimelinePhaseID ")
                cmd.Parameters.Add("@TimelinePhaseID", SqlDbType.Int).Value = objDB.DBSetInt(iJobPhaseID)
                Dim dt As DataTable = objDB.GetData(cmd)
                Dim lst = New List(Of Gantt.IAssignment)
                Dim qryTasks = dt.AsEnumerable().Select(Function(task) New Gantt.Assignment() With { _
                                                        .ID = task("TimelineTaskUserID"), _
                                                        .ResourceID = task("UserID"), _
                                                        .TaskID = task("TimelineTaskID"), _
                                                        .Units = task("UserPercentage") _
                                                    })
                lst.AddRange(qryTasks)
                Return lst
            End Function

            Public Overrides Function DeleteAssignment(assignment As Gantt.IAssignment) As Gantt.IAssignment
                Return MyBase.DeleteAssignment(assignment)
            End Function

            Public Overrides Function InsertAssignment(assignment As Gantt.IAssignment) As Gantt.IAssignment
                Return MyBase.InsertAssignment(assignment)
            End Function

            Public Overrides Function UpdateAssignment(assignment As Gantt.IAssignment) As Gantt.IAssignment
                Return MyBase.UpdateAssignment(assignment)
            End Function

            Public Overrides Function GetResources() As List(Of Gantt.IResource)
                Dim cmd As New SqlClient.SqlCommand("Users_Get")
                cmd.CommandType = CommandType.StoredProcedure
                Dim dt As DataTable = objDB.GetData(cmd)
                dt.DefaultView.RowFilter = "OrgID = 1 AND Enabled = 1"
                Dim lst = New List(Of Gantt.IResource)
                Dim qryTasks = dt.AsEnumerable().Select(Function(task) New Gantt.Resource() With { _
                                                        .ID = task("UserID"), _
                                                        .Text = task("UserFullName") _
                                                    })
                lst.AddRange(qryTasks)
                Return lst
            End Function
        End Class

        Public Class MZGanttTaskFactory
            Implements Telerik.Web.UI.Gantt.ITaskFactory

            Public Function CreateTask() As Gantt.Task Implements Gantt.ITaskFactory.CreateTask
                Return New MZTask
            End Function
        End Class

        Public Class MZTask
            Inherits Telerik.Web.UI.Gantt.Task

            Public Sub New()
                MyBase.New()
            End Sub

            Public Property TaskDuration() As String
                Get
                    Return DirectCast(If(ViewState("TaskDuration"), ""), String)
                End Get

                Set(ByVal value As String)
                    ViewState("TaskDuration") = value
                End Set
            End Property

            Public Property TaskDurationRemaining() As String
                Get
                    Return DirectCast(If(ViewState("TaskDurationRemaining"), ""), String)
                End Get

                Set(ByVal value As String)
                    ViewState("TaskDurationRemaining") = value
                End Set
            End Property

            Protected Overrides Function GetSerializationData() As IDictionary(Of String, Object)
                Dim dict = MyBase.GetSerializationData()

                dict("TaskDuration") = TaskDuration
                dict("TaskDurationRemaining") = TaskDurationRemaining

                Return dict
            End Function

            Public Overrides Sub LoadFromDictionary(values As IDictionary)
                MyBase.LoadFromDictionary(values)

                TaskDuration = DirectCast(values("TaskDuration"), String)
                TaskDurationRemaining = DirectCast(values("TaskDurationRemaining"), String)
            End Sub
        End Class

        Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
            RadGantt1.Provider = New GanttCustomProvider(objDB.DBGetInt(JobPhases.SelectedValue))
            RadGantt1.DataBind()
        End Sub


0
Bozhidar
Telerik team
answered on 11 Jul 2016, 07:26 AM
Hi,

Would you open a separate support ticket and attach a working sample project, so that we can inspect you concrete implementation?

Regards,
Bozhidar
Telerik by Progress
0
Sam
Top achievements
Rank 1
answered on 13 Jul 2016, 04:01 PM

In case anyone else ever has this issue, Bozhidar identified the problem - the Gantt control doesn't like the ParentID to be null. It needs to be nothing. So to fix my issue above, the line should be

.ParentID = If(task("ParentID").Equals(Convert.DBNull), Nothing, task("ParentID")), 

Thanks Bozhidar for the help on this. 

0
Bozhidar
Telerik team
answered on 14 Jul 2016, 06:25 AM
Hello,

Just to clarify - the problem was the DbNull value. In C# the value should be null and in VB it should be Nothing.

Regards,
Bozhidar
Telerik by Progress
0
Sam
Top achievements
Rank 1
answered on 14 Jul 2016, 09:44 AM
Got it. Thanks. 
Tags
Gantt
Asked by
David
Top achievements
Rank 1
Answers by
David
Top achievements
Rank 1
Bozhidar
Telerik team
Sam
Top achievements
Rank 1
Share this question
or