To reproduce: use the following code snippet and try to drag an item or click over a task item:
private ViewModel viewModel;
public Form1()
{
InitializeComponent();
viewModel = new ViewModel();
viewModel.Init();
viewModel.DateChanged += ViewModelOnDateChanged;
this.radGanttView1.Ratio = 0.3F;
this.radGanttView1.SplitterWidth = 7;
this.radGanttView1.TitleMember = "Name";
this.radGanttView1.ChildMember = "Id";
this.radGanttView1.EndMember = "End";
this.radGanttView1.ParentMember = "ParentId";
this.radGanttView1.ProgressMember = "Progress";
this.radGanttView1.StartMember = "Start";
this.radGanttView1.TaskDataMember = "TimingRows";
this.radGanttView1.LinkDataMember = "LinkRows";
this.radGanttView1.LinkStartMember = "StartId";
this.radGanttView1.LinkEndMember = "EndId";
this.radGanttView1.LinkTypeMember = "LinkType";
this.radGanttView1.DataSource = viewModel;
this.radGanttView1.Click += radGanttView1_Click;
}
private void radGanttView1_Click(object sender, EventArgs e)
{
this.radGanttView1.DataSource = null;
this.radGanttView1.DataSource = viewModel;
}
private void radGanttView1_MouseEnter(object sender, EventArgs e)
{
this.radGanttView1.DataSource = null;
this.radGanttView1.DataSource = viewModel;
}
private void ViewModelOnDateChanged(object sender, EventArgs eventArgs)
{
BeginInvoke(new Action(() =>
{
this.radGanttView1.DataSource = null;
this.radGanttView1.DataSource = viewModel;
}));
}
public class ViewModel
{
public event EventHandler DateChanged;
public BindingList<TimingRow> TimingRows { get; set; }
public BindingList<LinkRow> LinkRows { get; set; }
public ViewModel()
{
TimingRows = new BindingList<TimingRow>();
LinkRows = new BindingList<LinkRow>();
}
public void Init()
{
AddRow(1, 0, "group", 3, 12);
AddRow(2, 1, "Test1", 3, 4);
AddRow(3, 1, "Test2", 7, 8);
AddLink(2, 3, 1);
}
private void AddLink(int p1, int p2, int p3)
{
var link = new LinkRow(p1, p2, p3);
LinkRows.Add(link);
}
private void AddRow(int id, int parentId, string name, int addDays, int howLong)
{
var row = new TimingRow
{
Start = DateTime.Today.AddDays(addDays),
End = DateTime.Today.AddDays(addDays + howLong),
Id = id,
ParentId = parentId,
Name = name
};
row.DateChanged += RowOnDateChanged;
TimingRows.Add(row);
}
private void RowOnDateChanged(object sender, EventArgs eventArgs)
{
if (DateChanged != null)
DateChanged(this, EventArgs.Empty);
}
}
public class TimingRow
{
public event EventHandler DateChanged;
private DateTime start;
public string Name { get; set; }
public int Id { get; set; }
public int ParentId { get; set; }
public decimal Progress
{
get
{
return 0;
}
}
public virtual DateTime Start
{
get
{
return start;
}
set
{
if (start == value)
return;
if (DateChanged != null)
DateChanged(this, EventArgs.Empty);
start = value;
}
}
public virtual DateTime End { get; set; }
}
public class LinkRow
{
public int StartId { get; set; }
public int EndId { get; set; }
public int LinkType { get; set; }
public LinkRow(int startId, int endId, int linkType)
{
this.StartId = startId;
this.EndId = endId;
this.LinkType = linkType;
}
}
---------------------------------------------------------------------------------
WORKAROUND:
private void radGanttView1_CreateDataItem(object sender, Telerik.WinControls.UI.CreateGanttDataItemEventArgs e)
{
e.Item = new CustomGanttViewDataItem();
}
public class CustomGanttViewDataItem : GanttViewDataItem
{
protected override void OnNotifyPropertyChanged(PropertyChangedEventArgs e)
{
if (this.GanttViewElement != null)
{
base.OnNotifyPropertyChanged(e);
}
}
}
public class CustomGanttView : RadGanttView
{
public override string ThemeClassName
{
get
{
return typeof(RadGanttView).FullName;
}
}
protected override RadGanttViewElement CreateGanttViewElement()
{
return new CustomRadGanttViewElement();
}
}
public class CustomRadGanttViewElement : RadGanttViewElement
{
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadGanttViewElement);
}
}
protected override GanttViewGraphicalViewElement CreateGraphicalViewElement(RadGanttViewElement ganttView)
{
return new CustomGanttViewGraphicalViewElement(ganttView);
}
}
public class CustomGanttViewGraphicalViewElement : GanttViewGraphicalViewElement
{
protected override Type ThemeEffectiveType
{
get
{
return typeof(GanttViewGraphicalViewElement);
}
}
public CustomGanttViewGraphicalViewElement(RadGanttViewElement ganttView) : base(ganttView)
{
}
protected override IVirtualizedElementProvider<GanttViewDataItem> CreateElementProvider()
{
return new CustomGanttViewVirtualizedElementProvider(this);
}
}
public class CustomGanttViewVirtualizedElementProvider : GanttViewVirtualizedElementProvider
{
GanttViewBaseViewElement owner;
public CustomGanttViewVirtualizedElementProvider(GanttViewBaseViewElement owner) : base(owner)
{
this.owner = owner;
}
public override IVirtualizedElement<GanttViewDataItem> CreateElement(GanttViewDataItem data, object context)
{
GanttViewBaseItemElement element = this.OnItemElementCreating(data);
if (element != null)
{
return element;
}
if (owner is GanttViewTextViewElement)
{
return new GanttViewTextItemElement(owner as GanttViewTextViewElement);
}
else
{
if (data.Items.Count > 0)
{
return new GanttViewSummaryItemElement(this.owner as GanttViewGraphicalViewElement);
}
else if (data.Start == data.End)
{
return new GanttViewMilestoneItemElement(this.owner as GanttViewGraphicalViewElement);
}
return new CustomGanttViewTaskItemElement(this.owner as GanttViewGraphicalViewElement);
}
}
}
public class CustomGanttViewTaskItemElement : GanttViewTaskItemElement
{
public CustomGanttViewTaskItemElement(GanttViewGraphicalViewElement owner) : base(owner)
{
}
public override void Synchronize()
{
if (this.Data.GanttViewElement != null)
{
base.Synchronize();
}
}
}
How to reproduce:
1. Subscribe to radGanttView DoubleClick event.
2. Double click at any point on ragGanttView
Woraround:
1. Create a custom RadGanttView and override the OnMouseDoubleClick method
public class MyRadGanttView : RadGanttView
{
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
if (this.GanttViewElement.ProcessDoubleClick(e))
{
return;
}
MouseEventHandler item = (MouseEventHandler)base.Events[typeof(Control).GetField("EventMouseDoubleClick", BindingFlags.NonPublic | BindingFlags.Static).GetValue(this)];
if (item != null)
{
item(this, e);
}
}
}
To reproduce:
1. Drag and drop RadGanttView on the form
2. Populate with tasks and set the ReadOnly property to true.
3. Run the application and you will see that you can add links
Workaround:
Disable adding of links:
void radGanttView2_LinkAdding(object sender, GanttViewLinkAddingEventArgs e)
{
e.Cancel = true;
}
Workaround:
Sub New()
InitializeComponent()
Me.SetUpGantt()
Me.RadGanttView1.GanttViewElement.TextViewElement.Scroller.AllowHiddenScrolling = True
AddHandler Me.RadGanttView1.MouseUp, AddressOf Me.RadGanttView1_MouseUp
End Sub
Private Sub RadGanttView1_MouseUp(sender As Object, e As MouseEventArgs)
Dim location = e.Location
Dim splitter As GanttViewViewsSplitterElement = TryCast(Me.RadGanttView1.ElementTree.GetElementAtPoint(e.Location), GanttViewViewsSplitterElement)
If splitter IsNot Nothing Then
Me.RadGanttView1.GanttViewElement.TextViewElement.Scroller.Scrollbar.Value = Me.RadGanttView1.GanttViewElement.GraphicalViewElement.VScrollBar.Value
End If
End Sub
To reproduce:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'WeddingPlannerDataSet.Tasks' table. You can move, or remove it, as needed.
Me.TasksTableAdapter.Fill(Me.WeddingPlannerDataSet.Tasks)
'TODO: This line of code loads data into the 'WeddingPlannerDataSet.Links' table. You can move, or remove it, as needed.
Me.LinksTableAdapter.Fill(Me.WeddingPlannerDataSet.Links)
Me.RadGanttView1.GanttViewElement.TaskDataMember = "Tasks"
Me.RadGanttView1.GanttViewElement.ChildMember = "Id"
Me.RadGanttView1.GanttViewElement.ParentMember = "ParentId"
Me.RadGanttView1.GanttViewElement.TitleMember = "Title"
Me.RadGanttView1.GanttViewElement.StartMember = "Start"
Me.RadGanttView1.GanttViewElement.EndMember = "End"
Me.RadGanttView1.GanttViewElement.ProgressMember = "Progress"
Me.RadGanttView1.GanttViewElement.LinkDataMember = "Links"
Me.RadGanttView1.GanttViewElement.LinkStartMember = "StartId"
Me.RadGanttView1.GanttViewElement.LinkEndMember = "EndId"
Me.RadGanttView1.GanttViewElement.LinkTypeMember = "LinkType"
Me.RadGanttView1.GanttViewElement.DataSource = Me.WeddingPlannerDataSet
Me.RadGanttView1.Columns.Add("Start")
Me.RadGanttView1.Columns.Add("End")
Me.RadGanttView1.Ratio = 0.3
Me.RadGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = New DateTime(2006, 8, 20)
Me.RadGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = New DateTime(2007, 4, 2)
AddHandler Me.RadGanttView1.ItemChildIdNeeded, AddressOf ItemChildIdNeeded
AddHandler Me.RadGanttView1.ItemAdding, AddressOf ItemAdding
AddHandler Me.RadGanttView1.ItemAdded, AddressOf ItemAdded
End Sub
Dim integerIdCounter As Integer = 200
Private Sub ItemChildIdNeeded(sender As Object, e As Telerik.WinControls.UI.GanttViewItemChildIdNeededEventArgs)
Me.integerIdCounter += 1
e.ChildId = Me.integerIdCounter
End Sub
Workaround:
AddHandler Me.RadGanttView1.ContextMenuOpening, AddressOf RadGanttView1_ContextMenuOpening
Private Sub RadGanttView1_ContextMenuOpening(sender As Object, e As Telerik.WinControls.UI.GanttViewContextMenuOpeningEventArgs)
Dim item As RadMenuItem = DirectCast(e.Menu.Items(0), RadMenuItem)
AddHandler item.Items(0).Click, AddressOf ItemClick
End Sub
Private Sub ItemClick(sender As Object, e As EventArgs)
Me.RadGanttView1.GanttViewElement.GraphicalViewElement.Update(Telerik.WinControls.UI.RadGanttViewElement.UpdateActions.ExpandedChanged)
End Sub
Please look at the attached screenshot.
Workaround: you can replace the StackLayoutElement used in the GanttViewTimelineItemBottomStackElement with a DockLayoutPanel for example as follows:
Public Class CustomGanttViewTimelineItemElement
Inherits GanttViewTimelineItemElement
Public Sub New(data As GanttViewTimelineDataItem, graphicalViewElement As GanttViewGraphicalViewElement)
MyBase.New(data, graphicalViewElement)
End Sub
Dim dock As DockLayoutPanel
Protected Overrides Sub CreateChildElements()
MyBase.CreateChildElements()
dock = New DockLayoutPanel()
dock.StretchHorizontally = True
dock.LastChildFill = False
Me.Children.RemoveAt(Me.Children.Count - 1)
Me.Children.Add(dock)
End Sub
Protected Overrides Sub CalculateItems()
Me.SuspendLayout()
Dim cellInfo As GanttTimelineCellsInfo = Me.GraphicalViewElement.TimelineBehavior.GetTimelineCellInfoForItem(Me.Data, Me.GraphicalViewElement.TimelineRange)
While Me.dock.Children.Count > cellInfo.NumberOfcells
Me.dock.Children.RemoveAt(0)
End While
While Me.dock.Children.Count < cellInfo.NumberOfcells
Dim element As LightVisualElement = Me.GraphicalViewElement.TimelineBehavior.CreateElement()
Me.dock.Children.Add(element)
End While
Me.TopElement.Text = Me.GraphicalViewElement.TimelineBehavior.GetTimelineTopElementText(Me.Data)
For i As Integer = 0 To Me.dock.Children.Count - 1
DirectCast(Me.dock.Children(i), LightVisualElement).Text = Me.GraphicalViewElement.TimelineBehavior.GetTimelineBottomElementText(Me.Data, i + cellInfo.StartIndex)
Next
Me.ResumeLayout(True)
End Sub
Protected Overrides Function MeasureOverride(availableSize As SizeF) As SizeF
Dim clientRect As RectangleF = Me.GetClientRectangle(availableSize)
Dim width As Single = Me.Data.Width - Me.GraphicalViewElement.TimelineContainer.ItemSpacing + availableSize.Width - clientRect.Width
Me.TopElement.Measure(New SizeF(width, clientRect.Height / 2.0F))
Me.dock.Measure(New SizeF(width, clientRect.Height / 2.0F))
Return New SizeF(width, Me.TopElement.DesiredSize.Height + Me.dock.DesiredSize.Height)
End Function
Protected Overrides Function ArrangeOverride(finalSize As SizeF) As SizeF
Dim clientRect As RectangleF = Me.GetClientRectangle(finalSize)
Dim topRect As New RectangleF(clientRect.X, clientRect.Y, Me.DesiredSize.Width, clientRect.Height / 2.0F)
Me.TopElement.Arrange(topRect)
Dim bottomRect As New RectangleF(clientRect.X, topRect.Bottom, Me.DesiredSize.Width, clientRect.Height - topRect.Height)
Me.dock.Arrange(bottomRect)
Return clientRect.Size
End Function
End Class
Public Class CustomGanttViewTimelineElementProvider
Inherits GanttViewTimelineElementProvider
Public Sub New(owner As GanttViewGraphicalViewElement)
MyBase.New(owner)
End Sub
Public Overrides Function CreateElement(data As GanttViewTimelineDataItem, context As Object) As IVirtualizedElement(Of GanttViewTimelineDataItem)
Dim element As GanttViewTimelineItemElement = Me.OnItemElementCreating(data)
Return New CustomGanttViewTimelineItemElement(data, Owner)
End Function
End Class
How to reproduce: refer to the attached project
Workaround: reset the data source
private void Button1_Click(object sender, EventArgs e)
{
this.RadGanttView1.DataSource = null;
//TODO: This line of code loads data into the 'WeddingPlannerDataSet.Tasks' table. You can move, or remove it, as needed.
this.TasksTableAdapter.Fill(this.WeddingPlannerDataSet.Tasks);
//TODO: This line of code loads data into the 'WeddingPlannerDataSet.Links' table. You can move, or remove it, as needed.
this.LinksTableAdapter.Fill(this.WeddingPlannerDataSet.Links);
this.RadGanttView1.GanttViewElement.DataSource = this.WeddingPlannerDataSet
}
If one subscribes to the TimelineItemElementCreating and provides custom item elements for the timeline these elements are not used and default item elements are used instead.
WORKAROUND:
Create a custom element provider:
public class CustomGanttViewTimelineElementProvider : GanttViewTimelineElementProvider
{
public CustomGanttViewTimelineElementProvider(GanttViewGraphicalViewElement owner)
: base(owner)
{ }
public override IVirtualizedElement<GanttViewTimelineDataItem> CreateElement(GanttViewTimelineDataItem data, object context)
{
GanttViewTimelineItemElement element = this.OnItemElementCreating(data);
if (element != null)
{
return element;
}
return new GanttViewTimelineItemElement(data, this.Owner);
}
}
and assign it to the timeline container element provider:
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineContainer.ElementProvider = new CustomGanttViewTimelineElementProvider(this.radGanttView1.GanttViewElement.GraphicalViewElement);
This event should be fired when a task is modified either by the graphical view or by the columns on the left side. In the arguments you should have access to the changed property.
To reproduce:
public RadForm1()
{
InitializeComponent();
DataTable tasks = new DataTable("Tasks");
tasks.Columns.Add("Id", typeof(int));
tasks.Columns.Add("ParentId", typeof(int));
tasks.Columns.Add("Title", typeof(string));
tasks.Columns.Add("Start", typeof(DateTime));
tasks.Columns.Add("End", typeof(DateTime));
tasks.Columns.Add("Progress", typeof(decimal));
DataTable links = new DataTable("Links");
links.Columns.Add("StartId", typeof(int));
links.Columns.Add("EndId", typeof(int));
links.Columns.Add("LinkType", typeof(int));
tasks.Rows.Add(1, 0, "Summary task title", new DateTime(2010, 10, 8), new DateTime(2010, 10, 18), 30m);
tasks.Rows.Add(2, 1, "First child task title", new DateTime(2010, 10, 10), new DateTime(2010, 10, 12), 10);
tasks.Rows.Add(3, 1, "Second child task title", new DateTime(2010, 10, 12), new DateTime(2010, 10, 15), 20m);
tasks.Rows.Add(4, 1, "Milestone", new DateTime(2010, 10, 15), new DateTime(2010, 10, 15), 0m);
links.Rows.Add(2, 3, 1);
links.Rows.Add(3, 4, 1);
DataSet data = new DataSet();
data.Tables.Add(tasks.Copy());
data.Tables.Add(links);
this.radGridView1.DataSource = tasks;
radGridView1.BestFitColumns();
this.radGanttView1.CreateDataItem += radGanttView1_CreateDataItem;
this.radGanttView1.AllowSummaryEditing = true;
this.radGanttView1.GanttViewElement.TaskDataMember = "Tasks";
this.radGanttView1.GanttViewElement.ChildMember = "Id";
this.radGanttView1.GanttViewElement.ParentMember = "ParentId";
this.radGanttView1.GanttViewElement.TitleMember = "Title";
this.radGanttView1.GanttViewElement.StartMember = "Start";
this.radGanttView1.GanttViewElement.EndMember = "End";
this.radGanttView1.GanttViewElement.ProgressMember = "Progress";
this.radGanttView1.GanttViewElement.LinkDataMember = "Links";
this.radGanttView1.GanttViewElement.LinkStartMember = "StartId";
this.radGanttView1.GanttViewElement.LinkEndMember = "EndId";
this.radGanttView1.GanttViewElement.LinkTypeMember = "LinkType";
this.radGanttView1.GanttViewElement.DataSource = data;
this.radGanttView1.Columns.Add("Start");
this.radGanttView1.Columns.Add("End");
this.radGanttView1.Columns.Add("Progress");
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = new DateTime(2010, 10, 7);
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = new DateTime(2010, 12, 10);
}
You will notice that the start and end of the summary task are changed in the gantt view.
Workaround:
void radGanttView1_CreateDataItem(object sender, CreateGanttDataItemEventArgs e)
{
e.Item = new MyGanttViewDataItem();
}
public class MyGanttViewDataItem : GanttViewDataItem
{
protected override void OnChildAdded(GanttViewDataItem child)
{
if (this.Parent != null && !this.GanttViewElement.AllowSummaryEditing)
{
base.OnChildAdded(child);
}
}
protected override void OnChildRemoved(GanttViewDataItem child)
{
if (this.Parent != null && !this.GanttViewElement.AllowSummaryEditing)
{
base.OnChildRemoved(child);
}
}
}
To reproduce: - Add enough items so that the vertical scroll is shown. - Scroll so the first item is not visible. - Move one of the visible items.
To reproduce: 1. Drag and drop RadGanttView 2. Add summary task with 3 sub tasks 3. Set the ReadOnly property to true 4. Run the form and try to move summary task. The user should not be able to move summary task or any other task when is in read only mode. Workaround: You can set the following properties: this.radGanttView1.ReadOnly = true; this.radGanttView1.AllowSummaryEditing = false;
To reproduce:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = new DateTime(2010, 10, 9);
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = new DateTime(2010, 12, 10);
this.FillGanttViewWithData();
}
private void radGanttView1_SelectedItemChanged(object sender, GanttViewSelectedItemChangedEventArgs e)
{
var dateToFocus = e.Item.Start;
this.radGanttView1.GanttViewElement.GraphicalViewElement.ScrollTo(dateToFocus);
}
private void FillGanttViewWithData()
{
//setup data items
GanttViewDataItem item1 = new GanttViewDataItem();
item1.Start = new DateTime(2010, 10, 10);
item1.End = new DateTime(2010, 10, 15);
item1.Progress = 30m;
item1.Title = "Summary task.1. title";
GanttViewDataItem subitem11 = new GanttViewDataItem();
subitem11.Start = new DateTime(2010, 10, 10);
subitem11.End = new DateTime(2010, 10, 12);
subitem11.Progress = 10m;
subitem11.Title = "Sub-task.1.1 title";
GanttViewDataItem subitem12 = new GanttViewDataItem();
subitem12.Start = new DateTime(2010, 10, 12);
subitem12.End = new DateTime(2010, 10, 15);
subitem12.Progress = 20m;
subitem12.Title = "Sub-task.1.2 title";
//add subitems
item1.Items.Add(subitem11);
item1.Items.Add(subitem12);
this.radGanttView1.Items.Add(item1);
GanttViewDataItem item2 = new GanttViewDataItem();
item2.Start = new DateTime(2010, 10, 12);
item2.End = new DateTime(2010, 10, 18);
item2.Progress = 40m;
item2.Title = "Summary task.2. title";
GanttViewDataItem subitem21 = new GanttViewDataItem();
subitem21.Start = new DateTime(2010, 10, 12);
subitem21.End = new DateTime(2010, 10, 13);
subitem21.Progress = 10m;
subitem21.Title = "Sub-task.2.1 title";
GanttViewDataItem subitem22 = new GanttViewDataItem();
subitem22.Start = new DateTime(2010, 10, 13);
subitem22.End = new DateTime(2010, 10, 18);
subitem22.Progress = 30m;
subitem22.Title = "Sub-task.2.2 title";
GanttViewDataItem subitem23 = new GanttViewDataItem();
subitem23.Start = new DateTime(2010, 10, 18);
subitem23.End = new DateTime(2010, 10, 18);
subitem23.Title = "Sub-task.2.3 title";
//add subitems
item2.Items.Add(subitem21);
item2.Items.Add(subitem22);
item2.Items.Add(subitem23);
this.radGanttView1.Items.Add(item2);
//add links between items
GanttViewLinkDataItem link1 = new GanttViewLinkDataItem();
link1.StartItem = subitem11;
link1.EndItem = subitem12;
link1.LinkType = TasksLinkType.FinishToStart;
this.radGanttView1.Links.Add(link1);
GanttViewLinkDataItem link2 = new GanttViewLinkDataItem();
link2.StartItem = subitem21;
link2.EndItem = subitem22;
link2.LinkType = TasksLinkType.StartToStart;
this.radGanttView1.Links.Add(link2);
GanttViewLinkDataItem link3 = new GanttViewLinkDataItem();
link3.StartItem = subitem22;
link3.EndItem = subitem23;
link3.LinkType = TasksLinkType.FinishToStart;
this.radGanttView1.Links.Add(link3);
GanttViewTextViewColumn titleColumn = new GanttViewTextViewColumn("Title");
GanttViewTextViewColumn startColumn = new GanttViewTextViewColumn("Start");
GanttViewTextViewColumn endColumn = new GanttViewTextViewColumn("End");
this.radGanttView1.GanttViewElement.Columns.Add(titleColumn);
this.radGanttView1.GanttViewElement.Columns.Add(startColumn);
this.radGanttView1.GanttViewElement.Columns.Add(endColumn);
}
}
Workaround:
public class CustomGanttView : RadGanttView
{
protected override RadGanttViewElement CreateGanttViewElement()
{
return new CustomGanttViewElement();
}
public override string ThemeClassName
{
get { return typeof(RadGanttView).FullName; }
}
}
public class CustomGanttViewElement : RadGanttViewElement
{
protected override GanttViewGraphicalViewElement CreateGraphicalViewElement(RadGanttViewElement ganttView)
{
return new CustomGanttViewGraphicalViewElement(this);
}
protected override Type ThemeEffectiveType
{
get { return typeof(RadGanttViewElement); }
}
}
public class CustomGanttViewGraphicalViewElement : GanttViewGraphicalViewElement
{
public CustomGanttViewGraphicalViewElement(RadGanttViewElement ganttView)
: base(ganttView)
{ }
protected override Type ThemeEffectiveType
{
get { return typeof(GanttViewGraphicalViewElement); }
}
public override bool ScrollTo(DateTime dateTime)
{
if (dateTime < this.TimelineBehavior.AdjustedTimelineStart || dateTime > this.TimelineBehavior.AdjustedTimelineEnd)
{
return false;
}
float halfViewWidth = (float)this.ViewElement.Size.Width / 2f;
float x = (float)((dateTime - this.TimelineBehavior.AdjustedTimelineStart).TotalSeconds / this.OnePixelTime.TotalSeconds);
x -= halfViewWidth;
if (x < 0)
{
this.TimelineScroller.Scrollbar.Value = this.TimelineScroller.Scrollbar.Minimum;
}
else if (x > this.TimelineScroller.Scrollbar.Maximum)
{
this.TimelineScroller.Scrollbar.Value = this.TimelineScroller.Scrollbar.Maximum - this.TimelineScroller.Scrollbar.LargeChange;
}
else
{
this.TimelineScroller.Scrollbar.Value = (int)x;
}
return true;
}
}
To reproduce: use the following code snippet and perform the described steps below:
Sub New()
InitializeComponent()
PopulateData()
End Sub
Private Sub PopulateData()
Dim tasks As New DataTable("Tasks")
tasks.Columns.Add("Id", GetType(Integer))
tasks.Columns.Add("ParentId", GetType(Integer))
tasks.Columns.Add("Title", GetType(String))
tasks.Columns.Add("Start", GetType(DateTime))
tasks.Columns.Add("End", GetType(DateTime))
tasks.Columns.Add("Progress", GetType(Decimal))
Dim links As New DataTable("Links")
links.Columns.Add("StartId", GetType(Integer))
links.Columns.Add("EndId", GetType(Integer))
links.Columns.Add("LinkType", GetType(Integer))
Dim data As New DataSet()
data.Tables.Add(tasks)
data.Tables.Add(links)
tasks.Rows.Add(1, 0, "Summary task title", New DateTime(2010, 10, 10), New DateTime(2010, 10, 15), 30D)
tasks.Rows.Add(2, 1, "First child task title", New DateTime(2010, 10, 10), New DateTime(2010, 10, 12), 10)
tasks.Rows.Add(3, 1, "Second child task title", New DateTime(2010, 10, 12), New DateTime(2010, 10, 15), 20D)
tasks.Rows.Add(4, 1, "Milestone", New DateTime(2010, 10, 15), New DateTime(2010, 10, 15), 0D)
links.Rows.Add(2, 3, 1)
links.Rows.Add(3, 4, 1)
Me.RadGanttView1.GanttViewElement.TaskDataMember = "Tasks"
Me.RadGanttView1.GanttViewElement.ChildMember = "Id"
Me.RadGanttView1.GanttViewElement.ParentMember = "ParentId"
Me.RadGanttView1.GanttViewElement.TitleMember = "Title"
Me.RadGanttView1.GanttViewElement.StartMember = "Start"
Me.RadGanttView1.GanttViewElement.EndMember = "End"
Me.RadGanttView1.GanttViewElement.ProgressMember = "Progress"
Me.RadGanttView1.GanttViewElement.LinkDataMember = "Links"
Me.RadGanttView1.GanttViewElement.LinkStartMember = "StartId"
Me.RadGanttView1.GanttViewElement.LinkEndMember = "EndId"
Me.RadGanttView1.GanttViewElement.LinkTypeMember = "LinkType"
Me.RadGanttView1.GanttViewElement.DataSource = data
Me.RadGanttView1.Columns.Clear()
Me.RadGanttView1.Columns.Add("Start")
Me.RadGanttView1.Columns.Add("End")
Me.RadGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = New DateTime(2010, 10, 9)
Me.RadGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = New DateTime(2010, 12, 10)
End Sub
Private Sub RadButton1_Click(sender As Object, e As EventArgs) Handles RadButton1.Click
Dim selected = Me.RadGanttView1.SelectedItem.Title
Me.RadGanttView1.DataSource = Nothing
PopulateData()
Dim result = FindDataItem(selected, Me.RadGanttView1.Items)
If result IsNot Nothing Then
Me.RadGanttView1.SelectedItem = result
End If
End Sub
Dim found = Nothing
Private Function FindDataItem(selected As String, items As GanttViewDataItemCollection) As GanttViewDataItem
For Each item As GanttViewDataItem In items
If item.Title = selected Then
Return item
End If
Dim itm As GanttViewDataItem = FindDataItem(selected, item.Items)
If itm IsNot Nothing Then
Return itm
End If
Next
Return Nothing
End Function
1.Select a random task item
2.Click the button to rebind and restore the selection
As a result you will encounter a NullReferenceException.
Workaround: set the SelectedItem property to null/Nothing before rebinding
Improve the way to format easily summary task. Currently you need to cast all elements of summary element to change the BackColor.
Resolution:
There are three properties added to GanttViewSummaryElement which allow access to the inner elements: LeftElement, MiddleElement and RightElement.
Please take a look at the code example:
private void radGanttView1_GraphicalViewItemFormatting(object sender, GanttViewGraphicalViewItemFormattingEventArgs e)
{
GanttViewSummaryItemElement element = e.ItemElement as GanttViewSummaryItemElement;
if (element != null)
{
GanttViewSummaryElement summary = element.TaskElement as GanttViewSummaryElement;
summary.LeftElement.BackColor = Color.Blue;
summary.RightElement.BackColor = Color.Blue;
summary.MiddleElement.BackColor = Color.LightGreen;
summary.ProgressIndicatorElement.BackColor = Color.Red;
}
}
Description: Show context menu in RadGanttView (to enable adding, deleting tasks and setting progress) not only for the GraphicalViewElement, but also for the TextViewElement
To reproduce:
Bind to an object with a property of type double. Start the application and edit that same column. End the editing process and you will see an exception that decimal cannot be converted to double.
Workaround:
Create the following custom editor:
public class MySpinEditor : GanttViewSpinEditor
{
public override object Value
{
get
{
object value = base.Value;
return Convert.ChangeType(value, this.ValueType);
}
set
{
base.Value = value;
}
}
}
Subscribe to the EditorInitialized and EditorRequired events and use the following event handlers:
void GanttViewElement_EditorInitialized(object sender, GanttViewItemEditorInitializedEventArgs e)
{
GanttViewSpinEditor spinEditor = e.Editor as GanttViewSpinEditor;
if (spinEditor != null)
{
spinEditor.ValueType = typeof(double);
}
}
void GanttViewElement_EditorRequired(object sender, GanttViewEditorRequiredEventArgs e)
{
if (e.EditorType == typeof(GanttViewSpinEditor))
{
e.EditorType = typeof(MySpinEditor);
}
}
To reproduce: Add a RadGanttView to a form and set its Dock to Fill. Increase the size of the form. Add 3-4 events to the RadGanttView and start the application. Reduce the size of the form until the gantt is small enough so scrollbars should show. You will notice that the vertical scrollbars will not show.
Steps to reproduce: 1. Add a gantt view to a form and add two buttons, one for adding a new child to the selected item and one for removing the selected item. 2. Run the project and add child items to a normal task item - the item should become a summary item. 3. Remove all the child items of a summary item - it should become a normal task.
To reproduce: add a RadGanttView and populate it with data. Use the GraphicalViewItemFormatting event in order to change the e.ItemElement.TaskElement.Text. However, the changes are not applied.
Workaround:
private void radGanttView1_GraphicalViewItemFormatting(object sender, GanttViewGraphicalViewItemFormattingEventArgs e)
{
e.ItemElement.Tag = "Custom text";
}
public class CustomRadGanttView : RadGanttView
{
protected override RadGanttViewElement CreateGanttViewElement()
{
return new CustomRadGanttViewElement();
}
public override string ThemeClassName
{
get
{
return typeof(RadGanttView).FullName;
}
}
}
public class CustomRadGanttViewElement : RadGanttViewElement
{
public CustomRadGanttViewElement()
{
}
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadGanttViewElement);
}
}
protected override GanttViewGraphicalViewElement CreateGraphicalViewElement(RadGanttViewElement ganttView)
{
return new CustomGanttViewGraphicalViewElement(ganttView);
}
}
public class CustomGanttViewGraphicalViewElement : GanttViewGraphicalViewElement
{
public CustomGanttViewGraphicalViewElement(RadGanttViewElement ganttView) : base(ganttView)
{
}
protected override Type ThemeEffectiveType
{
get
{
return typeof(GanttViewGraphicalViewElement);
}
}
protected override IVirtualizedElementProvider<GanttViewDataItem> CreateElementProvider()
{
return new CustomGanttViewVirtualizedElementProvider(this);
}
}
public class CustomGanttViewVirtualizedElementProvider : GanttViewVirtualizedElementProvider
{
public CustomGanttViewVirtualizedElementProvider(GanttViewBaseViewElement owner) : base(owner)
{
}
public override IVirtualizedElement<GanttViewDataItem> CreateElement(GanttViewDataItem data, object context)
{
IVirtualizedElement<GanttViewDataItem> taskElement = base.CreateElement(data, context) ;
if (taskElement is GanttViewTaskItemElement)
{
FieldInfo fi = typeof(GanttViewVirtualizedElementProvider).GetField("owner", BindingFlags.NonPublic | BindingFlags.Instance);
GanttViewBaseViewElement owner = fi.GetValue(this) as GanttViewBaseViewElement ;
return new CustomGanttViewTaskItemElement(owner as GanttViewGraphicalViewElement);
}
return taskElement;
}
}
public class CustomGanttViewTaskItemElement:GanttViewTaskItemElement
{
public CustomGanttViewTaskItemElement(GanttViewGraphicalViewElement owner) : base(owner)
{
}
public override void Synchronize()
{
base.Synchronize();
if (this.Tag != null)
{
this.TaskElement.Text = this.Tag.ToString();
}
}
}