I have a RadChartView with a DateTimeContinuousAxis. I want my first and last labels to display a particular format (such as YYYY-MM-dd HH:mm:ss), but I want all my inner labels to show a different format (such as simply HH). I was going to do this with the LabelTemplateSelector based on the AxisLabelModel's CollectionIndex. However, I don't see a way to tell when I'm at the last label. The documentation of CollectionIndex says
"An AxisLabelModel for example will have this property set to the index of the label within the Telerik.Charting.AxisModel.Labels collection." However, AxisModel is an internal class, so I cannot access the Labels collection to tell how many labels are on the axis.
How do I get the number of axis labels in my LabelTemplateSelector?
4 Answers, 1 is accepted
Hi Brandon,
Thank you for the provided details.
You are right that in this particular case, there no easy way to check, which is the last label. I have a few things on my mind, but I will need to test them first. That is why I will need more time. I will contact you again in the next couple of days with my observation.
Regards,
Dinko
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hi Brandon,
Thank you for your patience.
You are right that there isn't a straight forward approach to get the current number of the labels inside the LabelTemplateSelector. After searching for a possible solution I think I was able to find one. What you can do is to set the Maximum property of the DateTimeContinuousAxis. This way you can compare the incoming label DateTime and the Maximum property. Keep in mind that if the last label is not visible in your project, you will need probably to just the MajorStep property so that the last label will be visible. You will also need to remove SmartLabels mode if such is applied.
public DataTemplate LastLabelTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var model = item as AxisLabelModel;
var categoricalAxis = container as DateTimeContinuousAxis;
if (categoricalAxis.Maximum.Date == ((DateTime)model.Content).Date)
{
return LastLabelTemplate;
}
return base.SelectTemplate(item, container);
}
Regards,
Dinko
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
The way my axis is currently set up, I manually adjust my TickOrigin, MajorStepUnit, and MajorStep on a Zoom/Pan so my labels have "nice" values (for instance, depending on the zoom level, labels will show ever 1, 5, 15, or 60 minutes). As the graph pans, I don't always have a label exactly on either edge of my axis, so I can't do an equality comparison with the ActualVisibleRange.Maximum. I set LastLabelVisibility="Visible" but that doesn't seem to affect it.
Here is the XAML for my HorizontalAxis.
<
telerik:DateTimeContinuousAxis
x:Name
=
"XAxis"
ElementBrush
=
"White"
LastLabelVisibility
=
"Visible"
IsStepRecalculationOnZoomEnabled
=
"False"
PlotMode
=
"OnTicks"
ContextMenu
=
"{StaticResource AxisContextMenu}"
ActualVisibleRangeChanged
=
"XAxis_OnActualVisibleRangeChanged"
ActualRangeChanged
=
"XAxis_OnActualRangeChanged"
PreviewMouseDoubleClick
=
"XAxis_OnPreviewMouseDoubleClick"
>
<
telerik:DateTimeContinuousAxis.Resources
>
<!-- Label templates for different zoom levels go here -->
</
telerik:DateTimeContinuousAxis.Resources
>
<
telerik:DateTimeContinuousAxis.LabelTemplateSelector
>
<
plot:DateTimeAxisLabelSelector
DateTimeFullLabelTemplate
=
"{StaticResource Fullemplate}"
DateTimeSecondLabelTemplate
=
"{StaticResource SecondTemplate}"
DateTimeMinuteLabelTemplate
=
"{StaticResource MinuteTemplate}"
DateTimeHourLabelTemplate
=
"{StaticResource HourTemplate}"
DateTimeDateLabelTemplate
=
"{StaticResource DateTemplate}"
DateTimeDayLabelTemplate
=
"{StaticResource DayTemplate}"
DateTimeMonthLabelTemplate
=
"{StaticResource MonthTemplate}"
/>
</
telerik:DateTimeContinuousAxis.LabelTemplateSelector
>
</
telerik:DateTimeContinuousAxis
>
And here is a portion of my code-behind for setting my axis label intervals:
private
void
XAxis_OnActualVisibleRangeChanged(Object sender, DateTimeRangeChangedEventArgs e)
{
var range = XAxis.ActualVisibleRange.Maximum - XAxis.ActualVisibleRange.Minimum;
// NOTE: Handling for additional zoom levels removed here for space.
if
(range > TimeSpan.FromMinutes(8))
{
XAxis.MajorStepUnit = TimeInterval.Minute;
XAxis.MajorStep = 1;
}
else
if
(range > TimeSpan.FromMinutes(3))
{
XAxis.MajorStepUnit = TimeInterval.Second;
XAxis.MajorStep = 15;
}
else
if
(range > TimeSpan.FromSeconds(30))
{
XAxis.MajorStepUnit = TimeInterval.Second;
XAxis.MajorStep = 5;
}
else
{
XAxis.MajorStepUnit = TimeInterval.Second;
XAxis.MajorStep = 1;
}
// Force the LabelTemplateSelector to re-evaluate. When the graph is panned/zoomed, a date label
// may move along the axis and its display format may need to change (e.g. it is no longer the
// first label, or the label interval has changed).
var labelTemplateSelector = XAxis.LabelTemplateSelector;
XAxis.LabelTemplateSelector =
null
;
XAxis.LabelTemplateSelector = labelTemplateSelector;
}
Any other ideas? Or is there something I'm missing for how to force an axis label at either edge of my axis?
Hi Brandon,
Thank you for the provided additional information.
Another approach that you can try is to manually get the last TextBlock on the axis using the ChildrenOfType<T>() extension method. You can wrap the execution of the code inside a Dispatcher.BeginInvoke() method. To change the TextBlock on the first label you can use the LabelTemplateSelector. I understand that this is not a perfect solution but still, you can consider it. Check the attached project which demonstrates this.
Another approach will be to remove the last label by setting the LastLabelVisibility property to Collapsed. Then you can use a Custom Annotation and manually position a TextBlock on the axis. The TextBlock will serve as the last label. Keep in mind that you will need to write custom code to calculate the date and its position.
Regards,
Dinko
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.