This topic describes how the xamGantt™ control is bound to an arbitrary tasks collection via ListBackedProject.
This topic contains the following sections:
The xamGantt control can be bound to a collection of custom tasks. In this case, create an instance of ListBackedProject and set it to the xamGantt Project property.
Provide a flat collection of custom tasks to the ListBackedProject, via its TaskItemsSource property and use the TaskPropertyMappings collection to define mappings between the custom task properties and the corresponding ProjectTask properties.
The following procedure illustrates populating a custom tasks collection from an XML file. This also results in the creation of a custom task Model and a ViewModel class that handles XML file operations.
The following screenshot previews the result.
To complete the procedure, you need the following:
A project with the following required NuGet package reference:
Infragistics.WPF.Gantt
For more information on setting up the NuGet feed and adding NuGet packages, you can take a look at the following documentation: NuGet Feeds.
A project with the XElementExtension class containing extension methods for working with xml data
A sample xml data source - TaskData.xml
Following is a conceptual overview of the process:
The following steps demonstrate how to bind a xamGantt control to a collection of custom tasks.
Create a custom task Model class
Create a custom task model that represents your data and implements the INotifyPropertyChanged interface.
See the CodeCode Example: Custom Task Model for more details.
Create a ViewModel class
Create a ViewModel class that handles the xml data loading and has a public member Tasks of type ObservableCollection of TaskModel that stores the custom task’s data.
See the CodeCode Example: ViewModel class for more details.
Add the required namespaces in the XAML page
Add the following namespaces at the beginning of the XAML page:
In XAML:
xmlns:ig="http://schemas.infragistics.com/xaml"
xmlns:viewmodel="clr-namespace:<Your ViewModel Namespace>"
Add a Grid in the page and bind its DataContext to the created ViewModel
Add a Grid container in the page and bind the Grid DataContext
property to the custom tasks view model class ListBackedProjectViewModel
.
In XAML:
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<viewmodel:ListBackedProjectViewModel x:Key="viewmodel"/>
</Grid.Resources>
<Grid.DataContext>
<Binding Source="{StaticResource viewmodel}" />
</Grid.DataContext>
…
</Grid>
Create a ListBackedProject and bind it to data
The ListBackedProject is a derived Project class that enables populating the tasks, based upon a provided flat collection of task information.
The ListBackedProject
is bound to the created custom tasks data stored in the Tasks public member via its TaskItemsSource property.
In XAML:
<ig:ListBackedProject x:Name="dataProvider"
TaskItemsSource="{Binding Tasks}">
<!-- Add ProjectTask Property Mappings Here -->
</ig:ListBackedProject>
Create project task property to custom task property mappings
Create a mappings collection using TaskPropertyMappings.
In every ProjectTaskPropertyMapping, the TaskProperty specifies a ProjectTask property and the DataObjectProperty specifies the corresponding custom task property.
For example, mapping the ProjectTask DataItemId property to the TaskID property defined in the custom TaskModel class.
In XAML:
<ig:ListBackedProject.TaskPropertyMappings>
<ig:ProjectTaskPropertyMappingCollection
UseDefaultMappings="True">
<!--Start Mandatory Project Task Property Mappings-->
<ig:ProjectTaskPropertyMapping
TaskProperty="DataItemId"
DataObjectProperty="TaskID" />
<ig:ProjectTaskPropertyMapping
TaskProperty="Tasks"
DataObjectProperty="Tasks" />
<ig:ProjectTaskPropertyMapping
TaskProperty="ConstraintType"
DataObjectProperty="ConstraintType" />
<ig:ProjectTaskPropertyMapping
TaskProperty="ConstraintDate"
DataObjectProperty="ConstraintDate" />
<ig:ProjectTaskPropertyMapping
TaskProperty="DurationFormat"
DataObjectProperty="DurationFormat" />
<!--End Mandatory Project Task Property Mappings-->
<!--Add the other Project Task Property Mappings-->
</ig:ProjectTaskPropertyMappingCollection>
</ig:ListBackedProject.TaskPropertyMappings>
See the CodeCode Example: Binding xamGantt to Custom Tasks Data in XAML via ListBackedProject for the full mappings list.
Set the xamGantt Project property to the created ListBackedProject
Set the xamGantt Project
property to the existing ListBackedProject:
In XAML:
<ig:XamGantt x:Name="gantt"
Project="{Binding ElementName=dataProvider}" />
The following table lists the code examples included in this topic.
This code example demonstrates a class that implements the INotifyPropertyChanged interface. Both the TaskModel and ListBackedProjectViewModel classes use this to notify the clients of properties changes.
In C#:
public class ObservableModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
In Visual Basic:
Public Class ObservableModel
Implements INotifyPropertyChanged
Public Event PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
The code example demonstrates a custom task Model that inherits the ObservableModel class.
You can add the Resources and sub-tasks as a comma separated string. For the sub-tasks, the comma separated string values that you enter need to match the properties that you map to the DataItemId property of the underlying ProjectTask for your ListBackedProject. The Predecessors also need to be added via comma separated string values.
In C#:
using Infragistics.Controls.Schedules;
public class TaskModel : ObservableModel
{
private string _taskId;
public string TaskID
{
get
{
return _taskId;
}
set
{
if (_taskId != value)
{
_taskId = value;
this.NotifyPropertyChanged("TaskID");
}
}
}
private string _tasks;
public string Tasks
{
get
{
return _tasks;
}
set
{
if (_tasks != value)
{
_tasks = value;
this.NotifyPropertyChanged("Tasks");
}
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
this.NotifyPropertyChanged("Name");
}
}
}
private ProjectTaskConstraintType _constraintType;
public ProjectTaskConstraintType ConstraintType
{
get
{
return _constraintType;
}
set
{
if (_constraintType != value)
{
_constraintType = value;
this.NotifyPropertyChanged("ConstraintType");
}
}
}
private DateTime? _constraintDate;
public DateTime? ConstraintDate
{
get
{
return _constraintDate;
}
set
{
if (_constraintDate != value)
{
_constraintDate = value;
this.NotifyPropertyChanged("ConstraintDate");
}
}
}
private ProjectDurationFormat _durationFormat;
public ProjectDurationFormat DurationFormat
{
get
{
return _durationFormat;
}
set
{
if (_durationFormat != value)
{
_durationFormat = value;
this.NotifyPropertyChanged("DurationFormat");
}
}
}
private TimeSpan _durationInHours;
public TimeSpan DurationInHours
{
get
{
return _durationInHours;
}
set
{
if (_durationInHours != value)
{
_durationInHours = value;
this.NotifyPropertyChanged("DurationInHours");
}
}
}
private DateTime _start;
public DateTime Start
{
get
{
return _start;
}
set
{
if (_start != value)
{
_start = value;
this.NotifyPropertyChanged("Start");
}
}
}
private bool _isMilestone = false;
public bool IsMilestone
{
get
{
return _isMilestone;
}
set
{
if (_isMilestone != value)
{
_isMilestone = value;
this.NotifyPropertyChanged("IsMilestone");
}
}
}
private bool _isInProgress = true;
public bool IsInProgress
{
get
{
return _isInProgress;
}
set
{
if (_isInProgress != value)
{
_isInProgress = value;
this.NotifyPropertyChanged("IsInProgress");
}
}
}
private DateTime? _deadlineDate;
public DateTime? DeadlineDate
{
get
{
return _deadlineDate;
}
set
{
if (_deadlineDate != value)
{
_deadlineDate = value;
this.NotifyPropertyChanged("DeadlineDate");
}
}
}
private bool _isUndetermined = false;
public bool IsUndetermined
{
get
{
return _isUndetermined;
}
set
{
if (_isUndetermined != value)
{
_isUndetermined = value;
this.NotifyPropertyChanged("IsUndetermined");
}
}
}
private string _resourceName;
public string ResourceName
{
get
{
return _resourceName;
}
set
{
if (_resourceName != value)
{
_resourceName = value;
this.NotifyPropertyChanged("ResourceName");
}
}
}
}
In Visual Basic:
Imports Infragistics.Controls.Schedules
Public Class TaskModel
Inherits ObservableModel
Private _taskId As String
Public Property TaskID() As String
Get
Return _taskId
End Get
Set(value As String)
If _taskId <> value Then
_taskId = value
Me.NotifyPropertyChanged("TaskID")
End If
End Set
End Property
Private _tasks As String
Public Property Tasks() As String
Get
Return _tasks
End Get
Set(value As String)
If _tasks <> value Then
_tasks = value
Me.NotifyPropertyChanged("Tasks")
End If
End Set
End Property
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(value As String)
If _name <> value Then
_name = value
Me.NotifyPropertyChanged("Name")
End If
End Set
End Property
Private _constraintType As ProjectTaskConstraintType
Public Property ConstraintType() As ProjectTaskConstraintType
Get
Return _constraintType
End Get
Set(value As ProjectTaskConstraintType)
If _constraintType <> value Then
_constraintType = value
Me.NotifyPropertyChanged("ConstraintType")
End If
End Set
End Property
Private _constraintDate As System.Nullable(Of DateTime)
Public Property ConstraintDate() As System.Nullable(Of DateTime)
Get
Return _constraintDate
End Get
Set(value As System.Nullable(Of DateTime))
If _constraintDate <> value Then
_constraintDate = value
Me.NotifyPropertyChanged("ConstraintDate")
End If
End Set
End Property
Private _durationFormat As ProjectDurationFormat
Public Property DurationFormat() As ProjectDurationFormat
Get
Return _durationFormat
End Get
Set(value As ProjectDurationFormat)
If _durationFormat <> value Then
_durationFormat = value
Me.NotifyPropertyChanged("DurationFormat")
End If
End Set
End Property
Private _durationInHours As TimeSpan
Public Property DurationInHours() As TimeSpan
Get
Return _durationInHours
End Get
Set(value As TimeSpan)
If _durationInHours <> value Then
_durationInHours = value
Me.NotifyPropertyChanged("DurationInHours")
End If
End Set
End Property
Private _start As DateTime
Public Property Start() As DateTime
Get
Return _start
End Get
Set(value As DateTime)
If _start <> value Then
_start = value
Me.NotifyPropertyChanged("Start")
End If
End Set
End Property
Private _isMilestone As Boolean = False
Public Property IsMilestone() As Boolean
Get
Return _isMilestone
End Get
Set(value As Boolean)
If _isMilestone <> value Then
_isMilestone = value
Me.NotifyPropertyChanged("IsMilestone")
End If
End Set
End Property
Private _isInProgress As Boolean = True
Public Property IsInProgress() As Boolean
Get
Return _isInProgress
End Get
Set(value As Boolean)
If _isInProgress <> value Then
_isInProgress = value
Me.NotifyPropertyChanged("IsInProgress")
End If
End Set
End Property
Private _deadlineDate As System.Nullable(Of DateTime)
Public Property DeadlineDate() As System.Nullable(Of DateTime)
Get
Return _deadlineDate
End Get
Set(value As System.Nullable(Of DateTime))
If _deadlineDate <> value Then
_deadlineDate = value
Me.NotifyPropertyChanged("DeadlineDate")
End If
End Set
End Property
Private _isUndetermined As Boolean = False
Public Property IsUndetermined() As Boolean
Get
Return _isUndetermined
End Get
Set(value As Boolean)
If _isUndetermined <> value Then
_isUndetermined = value
Me.NotifyPropertyChanged("IsUndetermined")
End If
End Set
End Property
Private _resourceName As String
Public Property ResourceName() As String
Get
Return _resourceName
End Get
Set(value As String)
If _resourceName <> value Then
_resourceName = value
Me.NotifyPropertyChanged("ResourceName")
End If
End Set
End Property
End Class
The code example demonstrates a ViewModel class that handles xml data loading and inherits the ObservableModel class.
A public property Tasks of type ObservableCollection of TaskModel objects is created and populated with data from XML file. The code uses extension methods implemented in the XElementExtension class.
In C#:
using Infragistics.Controls.Schedules;
public class ListBackedProjectViewModel : ObservableModel
{
public ListBackedProjectViewModel()
{
this.DownloadDataSource();
}
private ObservableCollection<TaskModel> _tasks;
public ObservableCollection<TaskModel> Tasks
{
get
{
return _tasks;
}
set
{
if (value != null)
{
_tasks = value;
}
NotifyPropertyChanged("Tasks");
}
}
private void DownloadDataSource()
{
ObservableCollection<TaskModel> dataSource = new ObservableCollection<TaskModel>();
XDocument xmlDoc = XDocument.Load("TaskData.xml");
IEnumerable<XElement> elements = xmlDoc.Root.Elements();
foreach (XElement el in elements)
{
TaskModel task = new TaskModel();
task.TaskID = el.Element("TaskID").GetString();
task.Name = el.Element("Name").GetString();
task.IsInProgress = el.Element("IsInProgress").GetBool();
task.Start = DateTime.Today.ToUniversalTime();
task.IsMilestone = el.Element("IsMilestone").GetBool();
task.DurationInHours = TimeSpan.FromHours(el.Element("DurationInHours").GetDouble());
task.IsUndetermined = el.Element("IsUndetermined").GetBool();
task.ResourceName = el.Element("ResourceName").GetString();
task.DurationFormat = ProjectDurationFormat.Days;
if (el.Element("DeadlineDateInHours").GetInt() != 0)
{
task.DeadlineDate = DateTime.Today.AddHours(el.Element("DeadlineDateInHours").GetInt()).ToUniversalTime();
}
dataSource.Add(task);
}
this._tasks = dataSource;
}
}
In Visual Basic:
Imports Infragistics.Controls.Schedules
Public Class ListBackedProjectViewModel
Inherits ObservableModel
Public Sub New()
Me.DownloadDataSource()
End Sub
Private _tasks As ObservableCollection(Of TaskModel)
Public Property Tasks() As ObservableCollection(Of TaskModel)
Get
Return _tasks
End Get
Set(value As ObservableCollection(Of TaskModel))
If value IsNot Nothing Then
_tasks = value
End If
NotifyPropertyChanged("Tasks")
End Set
End Property
Private Sub DownloadDataSource()
Dim dataSource As New ObservableCollection(Of TaskModel)()
Dim xmlDoc As XDocument = XDocument.Load("TaskData.xml")
Dim elements As IEnumerable(Of XElement) = xmlDoc.Root.Elements()
For Each el As XElement In elements
Dim task As New TaskModel()
task.TaskID = el.Element("TaskID").GetString()
task.Name = el.Element("Name").GetString()
task.IsInProgress = el.Element("IsInProgress").GetBool()
task.Start = DateTime.Today.ToUniversalTime()
task.IsMilestone = el.Element("IsMilestone").GetBool()
task.DurationInHours = TimeSpan.FromHours(el.Element("DurationInHours").GetDouble())
task.IsUndetermined = el.Element("IsUndetermined").GetBool()
task.ResourceName = el.Element("ResourceName").GetString()
task.DurationFormat = ProjectDurationFormat.Days
If el.Element("DeadlineDateInHours").GetInt() <> 0 Then
task.DeadlineDate = DateTime.Today.AddHours(el.Element("DeadlineDateInHours").GetInt()).ToUniversalTime()
End If
dataSource.Add(task)
Next
Me._tasks = dataSource
End Sub
End Class
The code example demonstrates creating a ListBackedProject, adding and binding a xamGantt control to data.
In XAML:
Code
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<viewmodel:ListBackedProjectViewModel x:Key="viewmodel" />
</Grid.Resources>
<Grid.DataContext>
<Binding Source="{StaticResource viewmodel}" />
</Grid.DataContext>
<ig:ListBackedProject x:Name="dataProvider"
TaskItemsSource="{Binding Tasks}">
<ig:ListBackedProject.TaskPropertyMappings>
<!-- Add Project Task Property Mappings Here -->
<ig:ProjectTaskPropertyMappingCollection UseDefaultMappings="True">
<!-- Start Mandatory Project Task Property Mappings -->
<ig:ProjectTaskPropertyMapping TaskProperty="DataItemId"
DataObjectProperty="TaskID" />
<ig:ProjectTaskPropertyMapping TaskProperty="Tasks"
DataObjectProperty="Tasks" />
<ig:ProjectTaskPropertyMapping TaskProperty="ConstraintType"
DataObjectProperty="ConstraintType" />
<ig:ProjectTaskPropertyMapping TaskProperty="ConstraintDate"
DataObjectProperty="ConstraintDate" />
<ig:ProjectTaskPropertyMapping TaskProperty="DurationFormat"
DataObjectProperty="DurationFormat" />
<!-- End Mandatory Project Task Property Mappings -->
<ig:ProjectTaskPropertyMapping TaskProperty="TaskName"
DataObjectProperty="Name" />
<ig:ProjectTaskPropertyMapping TaskProperty="Start"
DataObjectProperty="Start" />
<ig:ProjectTaskPropertyMapping TaskProperty="IsMilestone"
DataObjectProperty="IsMilestone" />
<ig:ProjectTaskPropertyMapping TaskProperty="IsActive"
DataObjectProperty="IsInProgress" />
<ig:ProjectTaskPropertyMapping TaskProperty="Duration"
DataObjectProperty="DurationInHours" />
<ig:ProjectTaskPropertyMapping TaskProperty="Deadline"
DataObjectProperty="DeadlineDate" />
<ig:ProjectTaskPropertyMapping TaskProperty="IsManual"
DataObjectProperty="IsUndetermined" />
<ig:ProjectTaskPropertyMapping TaskProperty="Resources"
DataObjectProperty="ResourceName" />
</ig:ProjectTaskPropertyMappingCollection>
</ig:ListBackedProject.TaskPropertyMappings>
</ig:ListBackedProject>
<ig:XamGantt x:Name="gantt"
Project="{Binding ElementName=dataProvider}"/>
</Grid>
The following topics provide additional information related to this topic.