Crosshair Cursor
- 10 minutes to read
The crosshair cursor allows users to track series point or indicator point coordinates on the chart, and helps users to compare different graphs.
The crosshair cursor comprises two intersecting horizontal and vertical lines (value line and argument line) with the corresponding axis labels at the end of the lines. The crosshair also contains a label (crosshair label) that is positioned on the line intersection. This label shows the argument and values for highlighted points. Initially the crosshair cursor displays only its argument line with the crosshair label. See the following section on how to display or hide crosshair elements: Display and Hide Crosshair Elements.
Enable or Disable Crosshair
The crosshair cursor is enabled initially. If you want to disable the crosshair at the chart level, set the chart’s CrosshairEnabled property to False. However, you can still enable crosshair for specific series or indicators. To do this, enable the XYSeries2D.CrosshairEnabled or Indicator.CrosshairEnabled property.
The following markup enables the crosshair cursor only for the second series:
<dxc:ChartControl CrosshairEnabled="False" >
<dxc:XYDiagram2D>
<dxc:LineSeries2D x:Name="series1"/>
<dxc:LineSeries2D x:Name="series2" CrosshairEnabled="True"/>
</dxc:XYDiagram2D>
</dxc:ChartControl>
Show Crosshair Programmatically
Call the XYDiagram2D.ShowCrosshair method to show the crosshair cursor. For example, the following code demonstrates how to show the crosshair programmatically on a chart’s Mouse.MouseUp event.
private void OnChartControlMouseUp(object sender, MouseButtonEventArgs e) {
XYDiagram2D xyDiagram = chartControl.Diagram as XYDiagram2D;
if (xyDiagram == null) return;
xyDiagram.ShowCrosshair(e.GetPosition(chartControl));
}
Pass the Point.Empty value to the XYDiagram2D.ShowCrosshair(Point) method to hide the crosshair cursor.
Specify Crosshair Snap Mode
The crosshair cursor’s snap mode specifies what points the crosshair cursor highlights: points with the nearest argument to the mouse cursor or the nearest value.
- Nearest Argument (Default)
- Nearest Value
The following markup specifies the CrosshairOptions.SnapMode property to make the crosshair cursor to highlight points with similar values:
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions SnapMode="NearestValue"/>
</dxc:ChartControl.CrosshairOptions>
Include Values That Are Out Of Chart Viewport
The crosshair cursor contains information about points that are in the chart visual range. Enable the CrosshairOptions.ShowOutOfRangePoints property to include points that are out of the chart viewport to the crosshair label.
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ShowOutOfRangePoints="True">
</dxc:ChartControl.CrosshairOptions>
Display and Hide Crosshair Elements
The Chart control can display the crosshair cursor with argument axis labels, value lines, and value axis labels in addition to the crosshair cursor’s label and argument line:
The following properties allow you to display and hide crosshair cursor elements:
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ShowCrosshairLabels="True"
ShowValueLabels="True"
ShowValueLine="True"
ShowArgumentLabels="True"
ShowArgumentLine="True"/>
<!--...-->
</dxc:ChartControl>
If a chart contains multiple series, the crosshair label displays a group header that shows the common argument for multiple points. To hide the group header, set the CrosshairOptions.ShowGroupHeaders property to False. You can specify the CrosshairOptions.GroupHeaderPattern property to format the header. See the following section for more information: Format Crosshair Content. For an example on how to customize the group header appearance, refer to the following section: Specify Crosshair Label Content Appearance.
Disable Highlighting Points
The crosshair cursor highlights points that a user hovers over. To disable this feature, set the CrosshairOptions.HighlightPoints property to False.
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions HighlightPoints="False"/>
</dxc:ChartControl.CrosshairOptions>
</dxc:ChartControl>
Format Crosshair Content
Format patterns allow you to manage how crosshair elements display their content. You can specify these patterns for the elements labeled in the following image:
The following code specifies patterns the crosshair cursor should apply to its elements’ text:
<dxc:ChartControl x:Name="chartControl">
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions GroupHeaderPattern="{}{A:MMMM d}"
ShowOnlyInFocusedPane="False"
ShowValueLabels="True"
ShowValueLine="True"/>
</dxc:ChartControl.CrosshairOptions>
<dxc:XYDiagram2D>
<dxc:StockSeries2D DisplayName="Stock Prices"
CrosshairLabelPattern="{}{S}:
Close: ${CV:.###}
High: ${HV:.###}">
<dxc:StockSeries2D.Indicators>
<dxc:RateOfChange DisplayName="Rate of Change"
CrosshairEnabled="True"
CrosshairLabelPattern="{}{I}:
Value: {V:F3}">
</dxc:RateOfChange>
</dxc:StockSeries2D.Indicators>
</dxc:StockSeries2D>
<dxc:XYDiagram2D.AxisY>
<dxc:AxisY2D>
<dxc:AxisY2D.CrosshairAxisLabelOptions>
<dxc:CrosshairAxisLabelOptions Pattern="{}{V:.##}"/>
</dxc:AxisY2D.CrosshairAxisLabelOptions>
</dxc:AxisY2D>
</dxc:XYDiagram2D.AxisY>
<dxc:XYDiagram2D.SecondaryAxesY>
<dxc:SecondaryAxisY2D>
<dxc:SecondaryAxisY2D.CrosshairAxisLabelOptions>
<dxc:CrosshairAxisLabelOptions Pattern="{}{V:.##}"/>
</dxc:SecondaryAxisY2D.CrosshairAxisLabelOptions>
</dxc:SecondaryAxisY2D>
</dxc:XYDiagram2D.SecondaryAxesY>
</dxc:XYDiagram2D>
</dxc:ChartControl>
Patterns can comprise plain text and placeholders with format specifiers. The following table lists available placeholders:
Pattern | Description |
---|---|
{S} | Displays the Series.DisplayName value. |
{A} | Displays a series point argument. |
{V} | Displays series point values. |
Stacked series-specific placeholders | |
{VP} | Displays series point values as percentages. |
{G} | Displays the name of a stacked group. |
{TV} | Displays a total group value. |
Bubble series-specific placeholders | |
{W} | Displays the weight. |
Range series-specific placeholders | |
{V1} | Displays the first value. |
{V2} | Displays the second value. |
{VD} | Displays the duration between the first and second data point values formatted using a common time format (e.g. HH:MM:SS for date time values and #.## for numeric values). |
{VDTD} | Displays the duration between the first and second date-time data point values in days. |
{VDTH} | Displays the duration between the first and second date-time data point values in hours. |
{VDTM} | Displays the duration between the first and second date-time data point values in minutes. |
{VDTS} | Displays the duration between the first and second date-time data point values in seconds. |
{VDTMS} | Displays the duration between the first and second date-time data point values in milliseconds. |
Financial series specific placeholders | |
{OV} | Displays the open value. |
{HV} | Displays the high value. |
{LV} | Displays the low value. |
{CV} | Displays the close value. |
Indicator specific placeholders | |
{I} | Displays an indicator name. |
{A} | Displays an indicator point’s argument. |
{V} | Displays a single-line indicator or MACD indicator point’s value. |
{SV} | Displays a MACD indicator signal line’s point value. |
{AV} | Displays the MovingAverage indicator value. |
{LV} | Displays the MovingAverage indicator lower envelope line point’s value. |
{UV} | Displays the Moving Average indicator upper envelope line point’s value. |
{T} | Displays the Error Bar indicator point’s top value. |
{B} | Displays the Error Bar indicator point’s bottom value. |
X-axis label specific placeholders | |
{A} | Displays a series point argument. |
Y-axis label specific placeholders | |
{V} | Displays series point values. |
{VP} | Displays series point values as percentages. |
In XAML, insert empty brackets into the beginning of a pattern if it starts with a placeholder. Refer to the following page for more information: {} Escape sequence / markup extension.
When the Chart control or a series is bound to data, the pattern may contain data field values in addition to placeholders. For example, the data source contains the Discount field and the pattern may look like: {S}: {V:F2} (Discount: {Discount:P0}).
More Examples
Specify Crosshair Label Position
The CrosshairOptionsBase.CommonLabelPosition property allows you specify the crosshair label position. You can use one of the following objects:
- CrosshairMousePosition (Default)
When this mode is used, the crosshair label follows the mouse cursor.
<dxc:ChartControl.CrosshairOptions> <dxc:CrosshairOptions> <dxc:CrosshairOptions.CommonLabelPosition> <dxc:CrosshairMousePosition Offset="12, 12"/> </dxc:CrosshairOptions.CommonLabelPosition> </dxc:CrosshairOptions> </dxc:ChartControl.CrosshairOptions>
- CrosshairFreePosition
When this mode is used, the crosshair label is attached to a corner of a dock target object.
<dxc:ChartControl.CrosshairOptions> <dxc:CrosshairOptions> <dxc:CrosshairOptions.CommonLabelPosition> <dxc:CrosshairFreePosition DockCorner="TopLeft" DockTarget="{Binding ElementName=chart}" Offset="12, 12"/> </dxc:CrosshairOptions.CommonLabelPosition> </dxc:CrosshairOptions> </dxc:ChartControl.CrosshairOptions>
Show Crosshair Content in a Legend
The crosshair cursor can display its content in a legend instead of the Crosshair label. The crosshair cursor uses a legend the Series.Legend or Indicator.Legend property specifies. If these properties are not defined, the crosshair cursor uses the first legend in the ChartControlBase.Legends collection.
The code below makes the crosshair cursor to display its content in a legend and configures legend settings:
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ContentShowMode="Legend"/>
</dxc:ChartControl.CrosshairOptions>
<dxc:ChartControl.Legends>
<dxc:Legend MaxCrosshairContentWidth="50"
MaxCrosshairContentHeight="20"
Orientation="Vertical"/>
</dxc:ChartControl.Legends>
<!-- ... -->
</dxc:ChartControl>
Note
Use the XYSeries2D.CrosshairContentShowMode and Indicator.CrosshairContentShowMode properties to specify an element the crosshair cursor should use for an individual series/indicator to display related information.
Display Individual Labels for Each Series/Indicator
The crosshair cursor can display individual labels for each series/indicator instead of a common label:
The following code demonstrates how to enable individual crosshair labels:
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions CrosshairLabelMode="ShowForEachSeries"/>
</dxc:ChartControl.CrosshairOptions>
Note
The crosshair label is automatically displayed with a beak in the CrosshairLabelMode.ShowForEachSeries and CrosshairLabelMode.ShowForNearestSeries modes.
Show the Crosshair Cursor Only in the Selected Pane
If the chart contains multiple panes, it draws the crosshair cursor with a common label through all panes. Enable the CrosshairOptions.ShowOnlyInFocusedPane property to show the crosshair only in the pane that a user hovers over with the mouse cursor.
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ShowOnlyInFocusedPane="True"/>
</dxc:ChartControl.CrosshairOptions>
<!-- ... -->
</dxc:ChartControl>
Set Line Snap Mode
The crosshair cursor supports the following modes that specify how to display crosshair lines:
- Auto (Default)
Crosshair lines are drawn through highlighted points.
- Free
Crosshair lines intersect at the mouse pointer position.
The following code snippet makes the crosshair draw argument and value lines at the mouse cursor position:
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions LinesMode="Free"/>
</dxc:ChartControl.CrosshairOptions>
Customize Crosshair Cursor Element Appearance
Specify Crosshair Label and Line Appearance
The Chart control allows you to fine-tune the appearance of crosshair cursor axis labels, lines, and popup:
The example below configures the crosshair cursor’s appearance to resemble to the one in the image above:
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ArgumentLineBrush="Orange" ValueLineBrush="DarkGray"
ShowArgumentLabels="True" ShowValueLabels="True"
ShowValueLine="True">
<dxc:CrosshairOptions.ArgumentLineStyle>
<dxc:LineStyle Thickness="2">
<dxc:LineStyle.DashStyle>
<DashStyle Dashes="2 5"/>
</dxc:LineStyle.DashStyle>
</dxc:LineStyle>
</dxc:CrosshairOptions.ArgumentLineStyle>
<dxc:CrosshairOptions.ValueLineStyle>
<dxc:LineStyle Thickness="2">
<dxc:LineStyle.DashStyle>
<DashStyle Dashes="2 2"/>
</dxc:LineStyle.DashStyle>
</dxc:LineStyle>
</dxc:CrosshairOptions.ValueLineStyle>
<dxc:CrosshairOptions.PopupTemplate>
<DataTemplate>
<Border Background="#C0FFFFFF" BorderBrush="#C0C0C0C0"
BorderThickness="1" Padding="4">
<ItemsControl ItemsSource="{Binding PresentationData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}"
ContentTemplate="{Binding Path=CrosshairSeriesLabelTemplate}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</DataTemplate>
</dxc:CrosshairOptions.PopupTemplate>
</dxc:CrosshairOptions>
</dxc:ChartControl.CrosshairOptions>
<dxc:XYDiagram2D>
<dxc:XYDiagram2D.SeriesTemplate>
<dxc:BarSideBySideSeries2D>
<dxc:BarSideBySideSeries2D.LegendMarkerTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Width="12" Height="12">
<Ellipse Stretch="Uniform" Fill="{Binding Path=MarkerBrush}"
Stroke="{Binding Path=MarkerLineBrush}" StrokeThickness="2"/>
</Grid>
<TextBlock Text="{Binding Path=Text}" Margin="4,0,0,0"
VerticalAlignment="Center" Width="55"/>
</StackPanel>
</DataTemplate>
</dxc:BarSideBySideSeries2D.LegendMarkerTemplate>
</dxc:BarSideBySideSeries2D>
</dxc:XYDiagram2D.SeriesTemplate>
<dxc:XYDiagram2D.AxisX>
<dxc:AxisX2D>
<dxc:AxisX2D.CrosshairLabelTemplate>
<DataTemplate>
<Grid>
<Border BorderThickness="1">
<Border.Background>
<SolidColorBrush Color="Lavender" />
</Border.Background>
<Label BorderThickness="1" BorderBrush="DarkGray"
FontStyle="Italic" Content="{Binding Path=Text}"
Padding="1" Foreground="Black"
FontSize="14"/>
</Border>
</Grid>
</DataTemplate>
</dxc:AxisX2D.CrosshairLabelTemplate>
</dxc:AxisX2D>
</dxc:XYDiagram2D.AxisX>
</dxc:XYDiagram2D>
</dxc:ChartControl>
Note
To specify the legend marker template for an indicator, use the Indicator.LegendMarkerTemplate property.
Specify Crosshair Label Content Appearance
Use the XYSeries2D.CrosshairLabelTemplate property to configure appearance for crosshair series items and group header.
You can access the crosshair group header in the first series crosshair label template. The following code configures the crosshair label’s group header and first series item appearance:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ResourceUsageChart"
xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
x:Class="ResourceUsageChart.MainWindow"
xmlns:dxt="http://schemas.devexpress.com/winfx/2008/xaml/charts/themekeys"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<dxc:ChartControl>
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ShowGroupHeaders="True"/>
</dxc:ChartControl.CrosshairOptions>
<dxc:ChartControl.Diagram>
<dxc:XYDiagram2D>
<dxc:LineSeries2D
x:Name="process1Memory"
ArgumentDataMember="Second"
DisplayName="Process 1"
ValueDataMember="Process1Memory">
<dxc:LineSeries2D.CrosshairLabelTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Background="LightBlue"
Text="{Binding HeaderText}"
HorizontalAlignment="Left"
VerticalAlignment="Center" Margin="0,2"
Foreground="{Binding Foreground}"
FontWeight="Bold"
FontStyle="{Binding FontStyle}"
FontSize="20"
FontStretch="{Binding FontStretch}"
FontFamily="{Binding FontFamily}"
Visibility="{Binding HeaderTextVisibility}"/>
<StackPanel Orientation="Horizontal" Margin="0,2">
<Grid Width="{DynamicResource {dxt:ChartControlThemeKey ResourceKey=LegendMarkerWidth}}"
Height="{DynamicResource {dxt:ChartControlThemeKey ResourceKey=LegendMarkerHeight}}"
VerticalAlignment="Top" Margin="0, 3, 0, 0"
Visibility="{Binding MarkerVisibility}">
<Rectangle Stretch="Uniform" Fill="Transparent"/>
<ContentPresenter Content="{Binding MarkerItem}" ContentTemplate="{Binding RelativeSource={RelativeSource Self}, Path= Content.MarkerTemplate}"/>
</Grid>
<TextBlock Grid.Column="1" Text="{Binding Text}"
VerticalAlignment="Center"
Margin="{DynamicResource {dxt:ChartControlThemeKey ResourceKey=LegendItemTextMargin}}"
Foreground="CadetBlue"
FontWeight="{Binding FontWeight}"
FontStyle="{Binding FontStyle}"
FontSize="{Binding FontSize}"
FontStretch="{Binding FontStretch}"
FontFamily="{Binding FontFamily}"
Visibility="{Binding TextVisibility}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</dxc:LineSeries2D.CrosshairLabelTemplate>
</dxc:LineSeries2D>
<dxc:LineSeries2D
x:Name="process2Memory"
DisplayName="Process 2"
ArgumentDataMember="Second"
ValueDataMember="Process2Memory"/>
<dxc:LineSeries2D
x:Name="process3Memory"
DisplayName="Process 3"
ArgumentDataMember="Second"
ValueDataMember="Process3Memory"/>
</dxc:XYDiagram2D>
</dxc:ChartControl.Diagram>
</dxc:ChartControl>
</Grid>
</Window>
More Examples
- How to: Customize the Appearance of Crosshair Axis Labels
- How to: Customize the Appearance of Crosshair Series Labels
Custom Draw the Crosshair Cursor
You can use the ChartControl.CustomDrawCrosshair event to customize the crosshair cursor’s appearance based on series or indicator data.
The following example shows how to use the CustomDrawCrosshair event to replicate crosshair cursor appearance to resemble the one in the image above:
<dxc:ChartControl CustomDrawCrosshair="ChartControlCustomDrawCrosshair">
<dxc:ChartControl.CrosshairOptions>
<dxc:CrosshairOptions ShowValueLabels="True"
ShowValueLine="True"
ShowArgumentLabels="True"/>
</dxc:ChartControl.CrosshairOptions>
<!--...-->
</dxc:ChartControl>
private void ChartControlCustomDrawCrosshair(object sender, CustomDrawCrosshairEventArgs e) {
e.CrosshairLineElement.Brush = Brushes.DarkSlateGray;
foreach(CrosshairAxisLabelElement axisLabelElement in e.CrosshairAxisLabelElements) {
axisLabelElement.Background = Brushes.Gray;
}
if(e.CrosshairElementGroups.Count != 0) {
foreach(CrosshairElement crosshairElement in e.CrosshairElementGroups[0].CrosshairElements) {
if(crosshairElement != null) {
crosshairElement.LabelElement.Text = string.Format("${0}M", crosshairElement.SeriesPoint.Value);
if(crosshairElement.SeriesPoint.Value > 10) {
crosshairElement.AxisLabelElement.Background = Brushes.Green;
crosshairElement.LineElement.Brush = Brushes.Green;
}
else {
crosshairElement.AxisLabelElement.Background = Brushes.Orange;
crosshairElement.LineElement.Brush = Brushes.Orange;
crosshairElement.LineElement.LineStyle = new LineStyle { Thickness = 1 };
}
}
}
}
}
Note
CrosshairElementGroup.IndicatorElements allows you to access indicator items when CrosshairOptions.ContentShowMode is Label.
Use the CustomDrawCrosshairEventArgs.CrosshairLegendElements collection to access the crosshair items when CrosshairOptions.ContentShowMode is Legend. For indicators, use CustomDrawCrosshairEventArgs.IndicatorLegendElements.