To reproduce:
this.radScheduler1.ActiveViewType = Telerik.WinControls.UI.SchedulerViewType.Month;
SchedulerMonthView monthView = this.radScheduler1.GetMonthView();
DateTime start= new DateTime(2018, 8, 1);
DateTime end= new DateTime(2018,8,31);
monthView.ShowFullMonth = true;
monthView.StartDate=start;
monthView.RangeStartDate = start;
monthView.RangeEndDate = end;
You will notice that you can navigate outside the specified range.
Workaround: manipulate the start date of the view:
this.radScheduler1.ActiveView.PropertyChanged += ActiveView_PropertyChanged;
DateTime start = new DateTime(2018, 8, 1);
DateTime end = new DateTime(2018,8,31);
private void ActiveView_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "StartDate" && (this.radScheduler1.ActiveView.StartDate < start || start.AddDays(30) < this.radScheduler1.ActiveView.StartDate)
|| e.PropertyName == "WeekCount" && this.radScheduler1.ActiveView.EndDate > end)
{
this.radScheduler1.ActiveView.StartDate = start;
}
}
How to reproduce:
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
this.radScheduler1.MouseMove += RadScheduler1_MouseMove;
this.radScheduler1.GroupType = GroupType.Resource;
Appointment appointment = new Appointment(DateTime.Today.AddHours(13), TimeSpan.FromHours(1), "Test Appointment");
this.radScheduler1.Appointments.Add(appointment);
}
private void RadScheduler1_MouseMove(object sender, MouseEventArgs e)
{
Point pt = this.radScheduler1.PointToClient(Cursor.Position);
SchedulerCellElement cell = this.radScheduler1.SchedulerElement.ElementTree.GetElementAtPoint(pt) as SchedulerCellElement;
if (cell != null)
{
if (cell.Date != null)
{
Console.WriteLine(cell.Date.ToShortTimeString());
}
}
}
private void button1_Click(object sender, EventArgs e)
{
switch (this.radScheduler1.ActiveViewType)
{
// showing the Day View
case SchedulerViewType.Day:
var theDayView = this.radScheduler1.GetDayView();
if (theDayView != null)
{
RulerPrimitive ruler = (this.radScheduler1.SchedulerElement.ViewElement as SchedulerDayViewElement).DataAreaElement.Ruler;
ruler.RangeFactor = ScaleRange.QuarterHour;
ruler.StartScale = 8;
ruler.EndScale = 18;
}
break;
}
}
}
Workaround: instead of accessing directly the ruler, apply the scaling on the view element
private void button2_Click(object sender, EventArgs e)
{
switch (this.radScheduler1.ActiveViewType)
{
// showing the Day View
case SchedulerViewType.Day:
var theDayView = this.radScheduler1.GetDayView();
if (theDayView != null)
{
theDayView.RangeFactor = ScaleRange.QuarterHour;
theDayView.RulerStartScale = 8;
theDayView.RulerEndScale = 18;
}
break;
}
}
How to rerproduce:
this.radScheduler1.AccessibleInterval.Start = new DateTime(2018, 7, 18, 00, 00, 00).AddMonths(-2);
this.radScheduler1.AccessibleInterval.End = new DateTime(2018, 7, 18, 00, 00, 00).AddMonths(2);
this.radScheduler1.ActiveViewType = Telerik.WinControls.UI.SchedulerViewType.Month;
Workaround:
public class CustomRadScheduler : RadScheduler
{
private FieldInfo schedulerFi;
private FieldInfo activeViewsFi;
private MethodInfo onPropertyChangedMi;
private MethodInfo setActiveViewMi;
protected override void CreateChildItems(RadElement parent)
{
base.CreateChildItems(parent);
this.activeViewsFi = typeof(RadScheduler).GetField("activeViews", BindingFlags.Instance | BindingFlags.NonPublic);
this.schedulerFi = typeof(SchedulerView).GetField("scheduler", BindingFlags.Instance | BindingFlags.NonPublic);
this.onPropertyChangedMi = typeof(SchedulerView).GetMethod("OnPropertyChanged", BindingFlags.Instance | BindingFlags.NonPublic);
this.setActiveViewMi = typeof(RadScheduler).GetMethod("SetActiveView", BindingFlags.Instance | BindingFlags.NonPublic);
}
public override string ThemeClassName
{
get
{
return typeof(RadScheduler).FullName;
}
}
/// <summary>
/// Gets or sets the type of the active view.
/// </summary>
/// <value>The type of the active view.</value>
[DefaultValue(SchedulerViewType.Day)]
[NotifyParentProperty(true)]
public override SchedulerViewType ActiveViewType
{
get
{
return base.ActiveViewType;
}
set
{
if (this.ActiveViewType != value && value == SchedulerViewType.Month)
{
SchedulerView newView;
Dictionary<SchedulerViewType, SchedulerView> activeViews = this.activeViewsFi.GetValue(this) as Dictionary<SchedulerViewType, SchedulerView>;
if (activeViews.ContainsKey(value))
{
newView = activeViews[value];
}
else
{
SchedulerView view = new CustomSchedulerMonthView();
this.schedulerFi.SetValue(view, this);
this.onPropertyChangedMi.Invoke(view, new object[] { new string[] { "Scheduler" } });
newView = view;
}
if (this.ActiveView != newView && newView != null)
{
this.setActiveViewMi.Invoke(this, new object[] { newView, true });
}
}
else
{
base.ActiveViewType = value;
}
}
}
}
public class CustomSchedulerMonthView : SchedulerMonthView
{
public override SchedulerView OffsetView(int offset)
{
if (this.ShowFullMonth)
{
DateTime dtStart = DateHelper.GetStartOfMonth(this.StartDate);
if (this.StartDate.Day > 1)
{
dtStart = dtStart.AddMonths(1);
}
dtStart = dtStart.AddMonths(offset);
return this.CreateViewWithStartDate(dtStart);
}
else
{
DateTime startDate = this.StartDate.Add(new TimeSpan(offset * this.OffsetTimeSpan.Ticks));
DateTimeInterval interval = new DateTimeInterval(startDate, this.GetEndDate(startDate));
if (this.Scheduler.AccessibleInterval.Contains(interval))
{
return this.CreateViewWithStartDate(startDate);
}
if (true)
{
}
return this.CreateViewWithStartDate(startDate);
}
}
protected override SchedulerView CreateViewWithStartDate(DateTime startDate)
{
SchedulerMonthView monthView = new SchedulerMonthView();
this.CopyPropertiesToView(monthView);
DateTimeInterval interval = new DateTimeInterval(startDate, this.GetEndDate(startDate));
if (interval.End > this.Scheduler.AccessibleInterval.End)
{
startDate = startDate.Add(new TimeSpan(-1 * this.OffsetTimeSpan.Ticks));
}
if (interval.Start < this.Scheduler.AccessibleInterval.Start)
{
startDate = startDate.Add(new TimeSpan(1 * this.OffsetTimeSpan.Ticks));
}
monthView.StartDate = startDate;
if (this.ShowFullMonth)
{
monthView.WeekCount = DateHelper.GetMonthDisplayWeeks(startDate, this.CurrentCulture.DateTimeFormat);
}
return monthView;
}
}
Use attached to reproduce.
Workaround:
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
radScheduler1.SchedulerElement.ViewElement.UpdateCells();
}
By design, the month view in RadScheduler stacks the appointments for a certain day considering the start time of the appointments and their duration. Internally, it uses MonthViewEventsComparer which would be great to be replaceable somehow.
If you set the ResourcesPerView property first to a value greater than the available resources in RadScheduler and then add even more resources, incorrect layout is displayed. Please refer to the attached gif file. However, note that if you first add the resources and then manipulate the ResourcesPerView property, everything is OK.
Workaround: set the ResourcesPerView property considering the available resources in RadScheduler
Private Sub RadSpinEditor2_ValueChanged(sender As Object, e As EventArgs) Handles RadSpinEditor2.ValueChanged
Me.RadScheduler1.Resources.Clear()
For i As Integer = 1 To Me.RadSpinEditor2.Value
Dim resource As New Telerik.WinControls.UI.Resource()
resource.Id = New EventId(i)
resource.Name = "Resource" & i
resource.Visible = True
resource.Color = Color.LightBlue
Me.RadScheduler1.Resources.Add(resource)
Next i
Me.RadScheduler1.GroupType = GroupType.Resource
Me.RadScheduler1.ActiveView.ResourcesPerView = Math.Min(Me.RadScheduler1.Resources.Count, Me.RadSpinEditor1.Value)
End Sub
It is possible to schedule multiple appointments in the same time period. In some scenario's this should be avoided. When the agenda can change from outside the scheduler, sometimes conflics will apear when the resource is not visible on the scheduler. It would be nice to have a list of all the conflicted appointments
To reproduce: - Use the search in the scheduler navigator. - Sort the grid by start/end date. - The values are sorted as strings. Workraround: - Use custom sorting.
How to reproduce:
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
Resource resource1 = new Resource();
resource1.Id = new EventId(1);
resource1.Name = "Resource 1";
resource1.Color = Color.Blue;
Resource resource2 = new Resource();
resource2.Id = new EventId(2);
resource2.Name = "Resource 2";
resource2.Color = Color.Green;
Resource resource3 = new Resource();
resource3.Id = new EventId(3);
resource3.Name = "Resource 3";
resource3.Color = Color.Red;
this.radScheduler1.Resources.Add(resource1);
this.radScheduler1.Resources.Add(resource2);
this.radScheduler1.Resources.Add(resource3);
}
private void RadForm1_Load(object sender, EventArgs e)
{
this.radScheduler1.GroupType = GroupType.Resource;
((SchedulerViewGroupedByResourceElementBase)this.radScheduler1.ViewElement).ResourceStartIndex = 2;
}
private void radButton1_Click(object sender, EventArgs e)
{
this.radScheduler1.Resources.RemoveAt(0);
}
}
Workaround:
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
Resource resource1 = new Resource();
resource1.Id = new EventId(1);
resource1.Name = "Resource 1";
resource1.Color = Color.Blue;
Resource resource2 = new Resource();
resource2.Id = new EventId(2);
resource2.Name = "Resource 2";
resource2.Color = Color.Green;
Resource resource3 = new Resource();
resource3.Id = new EventId(3);
resource3.Name = "Resource 3";
resource3.Color = Color.Red;
this.radScheduler1.Resources.Add(resource1);
this.radScheduler1.Resources.Add(resource2);
this.radScheduler1.Resources.Add(resource3);
}
private void RadForm1_Load(object sender, EventArgs e)
{
this.radScheduler1.GroupType = GroupType.Resource;
((SchedulerViewGroupedByResourceElementBase)this.radScheduler1.ViewElement).ResourceStartIndex = 2;
}
private void radButton1_Click(object sender, EventArgs e)
{
this.radScheduler1.GroupType = GroupType.None;
this.radScheduler1.Resources.RemoveAt(0);
this.radScheduler1.GroupType = GroupType.Resource;
}
}
To reproduce: run the sample project and follow the illustrates steps from the gif file.
Workaround: close the tooltip programmatically:
private void radScheduler1_AppointmentMouseDown(object sender, SchedulerAppointmentMouseEventArgs e)
{
if (tooltip != null)
{
tooltip.Hide(this.radScheduler1);
}
}
ToolTip tooltip = null;
private void radScheduler1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e)
{
AppointmentElement app = sender as AppointmentElement;
if (app != null)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++)
{
sb.AppendLine(app.Appointment.Summary + i + " " + app.Appointment.Summary + i + i + " " + app.Appointment.Summary);
}
e.ToolTipText = sb.ToString();
tooltip = e.ToolTip;
}
}
Run the application on a Windows 10 machine and scroll to the bottom. Please refer to the attached gif file.
This feature is required for OpenEdge scenarios. A common case is that the resource_id field is stored as an integer field in your DataSource. But RadScheduler needs EventId type. You can have a look at the Appointment.ResourceId property which expects EventId value, not an integer. It is necessary to use a SchedulerMapping in this case and convert the integer value to EventId used by RadScheduler and convert the EventId to an integer used by your DataSource. This conversion is performed by the ConvertToDataSource and ConvertToScheduler callbacks. It is responsible for the proper conversion of the integer resource_id value coming from the DataSource to the RadScheduler's EventId. Additional information for the SchedulerMapping is available here: http://docs.telerik.com/devtools/winforms/scheduler/data-binding/scheduler-mapping In C#, it is just necessary to specify the name of the callback which will handle the conversion but it seems to be a problem in ABL. It is required to have events.
By default, each Appointment has two properties: ResourceId and ResourceIds. Usually, the ResourceId is used when you have only a single resource for the appointment. In case you have multiple resources for an appointment the ResourceIds collection is used. However, the current implementation of the EditAppointmentDialog uses a RadDropDownList for the resource selection. Thus, the user is not allowed to create an appointment and assign two resources to it. It can be achieved only programmatically. This is a common scenario when creating a meeting and you have at least two participants. A possible solution would be to replace the resources RadDropDownList with a RadCheckedDropDownList. Thus, the user will be able to select multiple resources.
To reproduce:
1. Add a RadScheduler and associate a RadSchedulerNavigator to it.
2. Change the culture to "fa-IR". When running the application you will notice that the time range in the navigator is not displayed correctly considering the culture of the associate RadScheduler.
Note: you can set the SchedulerNavigatorElement.DateFormat property to "dd dddd". Thus, the time range should be displayed in a similar way as the header cells in RadScheduler.
Workaround: you can controls what to be displayed in the navigator by the SchedulerNavigatorElement.DateLabel.Text property.
this.radScheduler1.Culture = new System.Globalization.CultureInfo("fa-IR");
string start = this.radScheduler1.ActiveView.StartDate.ToString(this.radSchedulerNavigator1.SchedulerNavigatorElement.DateFormat, this.radScheduler1.Culture);
string end = this.radScheduler1.ActiveView.EndDate.ToString(this.radSchedulerNavigator1.SchedulerNavigatorElement.DateFormat, this.radScheduler1.Culture);
this.radSchedulerNavigator1.SchedulerNavigatorElement.DateLabel.Text = start + " - " + end;
This is reproducible not only with Material theme but with the other themes as well.
Workaround:
private void radScheduler1_CellFormatting(object sender, Telerik.WinControls.UI.SchedulerCellEventArgs e)
{
e.CellElement.ZIndex = 0;
}
If you want to show the borders for the weekdays, the left most border is not shown because another element is over the cell. It is not possible to hide this top left cell and show the left border for Sunday.
Please refer to the attached screenshot from Outlook.
Please refer to the attached sample project and screenshot. Note that if RadScheduler is not grouped by resources, the scrollbar works as expected.
Please refer to the attached sample project. When you toggle the button the Visible property for the first resource is inverted. However, it doesn't take effect in RadScheduler and the resource is always visible. Workaround: Currently, if you want to hide some of the resources, you should remove them from the Resources collection of RadScheduler. When you want to use them again, you should just add them to the same collection.