Please use the following code snippet:
public partial class Form1 : Form
{
public class VM
{
public string Text
{
get; set;
}
public DateTime Start
{
get; set;
}
public DateTime End
{
get; set;
}
}
public Form1()
{
InitializeComponent();
var ViewModel = new VM[]
{
new VM()
{
Text = "CrashTest",
Start = new DateTime(2021, 11, 3, 10, 0, 0),
End = new DateTime( 2021, 11, 3, 23, 0, 0 ) //crash
//End = new DateTime( 2021, 11, 3, 22, 0, 0 ) //No crash
},
};
radGanttView1.GanttViewElement.GraphicalViewElement.OnePixelTime = new TimeSpan( 0, 1, 0 );
radGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = ViewModel.Min( T => T.Start );
radGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = ViewModel.Max( T => T.End );
radGanttView1.GanttViewElement.GraphicalViewElement.TimelineRange = TimeRange.Day;
radGanttView1.GanttViewElement.ChildMember = "Text";
radGanttView1.GanttViewElement.TitleMember = "Text";
radGanttView1.GanttViewElement.StartMember = "Start";
radGanttView1.GanttViewElement.EndMember = "End";
radGanttView1.DataSource = ViewModel;
}
}
Currently, the possible solution that I can suggest is to increase the view's end with 1 hour:
radGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = ViewModel.Max( T => T.End.AddHours(1));
Please refer to the attached gif file.
Steps :Please use the following code snippet. Activate the editor for a cell and click another cell:
private DataSet weddingPlan;
public DataSet WeddingPlan {
get
{
if(weddingPlan == null)
{
weddingPlan = new DataSet();
using (StreamReader rdr = new StreamReader("TelerikWeddingPlanner.xml"))
{
weddingPlan.ReadXml(rdr);
}
}
return weddingPlan;
}
}
public Form1()
{
InitializeComponent();
// Events
this.radGanttView1.GanttViewElement.EditorRequired += GanttViewElement_EditorRequired;
this.radGanttView1.GanttViewElement.EditorInitialized += GanttViewElement_EditorInitialized;
this.radGanttView1.GanttViewElement.ItemValidating += GanttViewElement_ItemValidating;
this.radGanttView1.GanttViewElement.ItemValidated += GanttViewElement_ItemValidated;
this.radGanttView1.GanttViewElement.ItemEdited += GanttViewElement_ItemEdited;
}
private void GanttViewElement_DoubleClick(object sender, EventArgs e)
{
Debug.WriteLine("GanttViewElement_DoubleClick");
}
private void GanttViewElement_EditorRequired(object sender, GanttViewEditorRequiredEventArgs e)
{
Debug.WriteLine("GanttViewElement_EditorRequired");
}
private void GanttViewElement_EditorInitialized(object sender, GanttViewItemEditorInitializedEventArgs e)
{
Debug.WriteLine("GanttViewElement_EditorInitialized");
}
private void GanttViewElement_ItemValidated(object sender, GanttViewItemValidatedEventArgs e)
{
Debug.WriteLine("GanttViewElement_ItemValidated");
}
private void GanttViewElement_ItemValidating(object sender, GanttViewItemValidatingEventArgs e)
{
Debug.WriteLine("GanttViewElement_ItemValidating");
Debug.WriteLine(e.Column.FieldName);
e.Cancel = true;
}
private void GanttViewElement_ItemEdited(object sender, GanttViewItemEditedEventArgs e)
{
Debug.WriteLine("GanttViewElement_ItemEdited");
}
private void Form1_Load(object sender, EventArgs e)
{
this.radGanttView1.DataSource = WeddingPlan;
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 = "Finish";
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.Columns.Add(new GanttViewTextViewColumn("Id"));
this.radGanttView1.GanttViewElement.Columns.Add(new GanttViewTextViewColumn("ParentId"));
this.radGanttView1.GanttViewElement.Columns.Add(new GanttViewTextViewColumn("Title"));
this.radGanttView1.GanttViewElement.Columns.Add(new GanttViewTextViewColumn("Start"));
this.radGanttView1.GanttViewElement.Columns.Add(new GanttViewTextViewColumn("Finish"));
this.radGanttView1.GanttViewElement.Columns[0].Visible = false;
this.radGanttView1.GanttViewElement.Columns[1].Visible = false;
this.radGanttView1.GanttViewElement.Columns[2].Width = 350;
this.radGanttView1.GanttViewElement.Columns[3].Width = 120;
this.radGanttView1.GanttViewElement.Columns[4].Width = 120;
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineRange = TimeRange.Month;
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineStart = new DateTime(2006, 8, 21);
this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineEnd = new DateTime(2007, 4, 3);
}
private void radGanttView1_ItemChildIdNeeded(object sender, GanttViewItemChildIdNeededEventArgs e)
{
int max = int.MinValue;
foreach (DataRow row in (this.radGanttView1.DataSource as DataSet).Tables[0].Rows)
{
if (int.Parse(row[0].ToString()) > max)
{
max = int.Parse(row[0].ToString());
}
}
e.ChildId = ++max;
}
Hey !
I need to know if you plan the development of a new function :
When you are in the list of your tasks, i want to navigate with the keyboard.
Im' Here :
And when i navigate in the list with the keyboard, i need to see the last column on the same task :
The focus is good but the horizontal scrollBar is on the same place and we can't the the all value of the cell.
Can we plan the improvment ? Or do you have a clean solution?
If you need more informations,
don't hesitate to contact me
Regards,
Valériane
It would be useful if the control takes advantage of the RadSpreadProcessing, RadPdfProcessing and RadWordsProcessing. This will allow developers to easily export the control's contents to the desired format.
To reproduce: run the sample project and scroll to the end of the view. You will notice that the tasks are not properly aligned. You can increase the GraphicalViewElement.OnePixelTime in order to make the alignment even worse. Workaround: Adjust the GraphicalViewElement.OnePixelTime in order to obtain the correct alignment.
How to reproduce: this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineRange = Telerik.WinControls.UI.TimeRange.DayQuarterHours; this.radGanttView1.GanttViewElement.GraphicalViewElement.AutomaticTimelineTimeRange = true; this.radGanttView1.GanttViewElement.GraphicalViewElement.OnePixelTime = new TimeSpan(0, 0, 15); Workaround: at the moment the Gantt control does not support an automatic timeline range for day quarter hours. The TimeRange.DayQuarterHours is similar to the half days and they should be handled the same way when in automatic timeline. If possible TimeRange.DayHalfHours this.radGanttView1.GanttViewElement.GraphicalViewElement.TimelineRange = Telerik.WinControls.UI.TimeRange.DayHalfHours;
How to reproduce: 1. Run the project 2. Press the radButton1 3. Edit description of the first line (Line whose Identifier is TestProject1) 4. Clicking some other line to end the edit causes the ASSERT to come up
To reproduce: please refer to the attached sample project. Try to edit the title for one of the child tasks in the grid and click the Workaround: private void radGanttView1_ItemChanged(object sender, Telerik.WinControls.UI.GanttViewItemChangedEventArgs e) { IEditableObject editebleObejct = e.Item.DataBoundItem as IEditableObject; if (editebleObejct != null) { editebleObejct.EndEdit(); } }
To reproduce: public Form1() { 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)); DataSet data = new DataSet(); data.Tables.Add(tasks); data.Tables.Add(links); Random rand = new Random(); int cnt = 3000; int cnt2 = 6000; for (int i = 1; i < cnt; i++) { tasks.Rows.Add(i, 0, "Summary task title", DateTime.Now.AddDays(i), DateTime.Now.AddDays(i + 5), 30m); } for (int i = cnt; i < cnt2; i++) { tasks.Rows.Add(i, rand.Next(1, cnt), "First child task title", new DateTime(2010, 10, 10), new DateTime(2010, 10, 12), 10); } for (int i = 0; i < 2000; i++) { links.Rows.Add(rand.Next(cnt, cnt2), rand.Next(1, cnt), 1); } 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"); } private void radButton1_Click(object sender, EventArgs e) { this.radGanttView1.PrintPreview(); }
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
Currently when you set the TimelineRange property to TimeRange.Week displays two elements (the TopElement with weeks and the BottomElement with days). There are cases where users want to display single timeline - only weeks, days, quarters or years independent of the second timeline.
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
The position of splitter should allow to be fixed while resizing the control. Users want to be able to set the splitter next to the last column of TextViewElement when resizing.
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
Add functionality to sort tasks alphabetically, by date, by progress.