Populating Gantt with custom Provider

13 posts, 1 answers
  1. David
    David avatar
    5 posts
    Member since:
    Jul 2015

    Posted 03 Jul 2015 Link to this post

    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);
            }
        }

  2. David
    David avatar
    5 posts
    Member since:
    Jul 2015

    Posted 03 Jul 2015 in reply to David Link to this post

    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.

  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Bozhidar
    Admin
    Bozhidar avatar
    1101 posts

    Posted 08 Jul 2015 Link to this post

    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
  5. David
    David avatar
    5 posts
    Member since:
    Jul 2015

    Posted 08 Jul 2015 Link to this post

    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.

  6. David
    David avatar
    5 posts
    Member since:
    Jul 2015

    Posted 08 Jul 2015 Link to this post

    FunctionsClient is a reference to a WCF service if that is of any help.
  7. Answer
    Bozhidar
    Admin
    Bozhidar avatar
    1101 posts

    Posted 10 Jul 2015 Link to this post

    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
  8. David
    David avatar
    5 posts
    Member since:
    Jul 2015

    Posted 20 Jul 2015 in reply to Bozhidar Link to this post

    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)?

  9. Bozhidar
    Admin
    Bozhidar avatar
    1101 posts

    Posted 20 Jul 2015 Link to this post

    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
  10. Sam
    Sam avatar
    60 posts
    Member since:
    Mar 2011

    Posted 08 Jul in reply to Bozhidar Link to this post

    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


  11. Bozhidar
    Admin
    Bozhidar avatar
    1101 posts

    Posted 11 Jul Link to this post

    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
  12. Sam
    Sam avatar
    60 posts
    Member since:
    Mar 2011

    Posted 13 Jul Link to this post

    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. 

  13. Bozhidar
    Admin
    Bozhidar avatar
    1101 posts

    Posted 14 Jul Link to this post

    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
  14. Sam
    Sam avatar
    60 posts
    Member since:
    Mar 2011

    Posted 14 Jul Link to this post

    Got it. Thanks. 
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017