How to Create and Dynamically Update Target Line for WPF Chart?
This article provides a detailed walkthrough on how to create and dynamically update target line in WPF Chart.
The SfChart includes support for Annotations, enabling the addition of various types of annotations to enhance chart visualization. Using HorizontalLineAnnotation, you can create and dynamically adjust the target line.
The Horizontal Line Annotation includes following property:
- Y1 - Represents the Y1 Coordinate of the horizontal line Annotation.
- Stroke - Represents the brush for the horizontal line annotation outline.
- StrokeThickness - Represents the thickness of the horizontal line annotation outline.
- StrokeDashArray - Represents the DashArray of the horizontal line annotation stroke.
- Text - Gets or sets the description text for horizontal line Annotation.
Learn step-by-step instructions and gain insights to create and dynamically update the target line.
Step 1: The layout is created using a grid with two columns.
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
Step 2: In first column of grid layout, initialize the SfChart and add the axes and series as shown below.
XAML
<chart:SfChart Grid.Column="0">
<chart:SfChart.PrimaryAxis>
<chart:CategoryAxis EdgeLabelsDrawingMode="Fit" ShowGridLines="False" Header="Months"/>
</chart:SfChart.PrimaryAxis>
<chart:SfChart.SecondaryAxis>
<chart:NumericalAxis x:Name="Y_Axis" Minimum="0" Maximum="20000" Interval="5000" ShowGridLines="False" Header="Revenue" LabelFormat="'$'0" PlotOffsetEnd="30"/>
</chart:SfChart.SecondaryAxis>
<chart:ColumnSeries ItemsSource="{Binding Data}"
XBindingPath="Months"
YBindingPath="Revenue"
Palette="Custom"
Opacity="0.7">
<chart:ColumnSeries.ColorModel>
<chart:ChartColorModel>
<chart:ChartColorModel.CustomBrushes>
......
</chart:ChartColorModel.CustomBrushes>
</chart:ChartColorModel>
</chart:ColumnSeries.ColorModel>
</chart:ColumnSeries>
</chart:SfChart>
Step 3: The HorizontalLineAnnotation is initialized within the Annotations collection of the SfChart to mark a dynamic target value on the Y-axis. The Y1 property is data-bound to the ViewModel, allowing the target line to adjust dynamically when the value changes.
XAML
<chart:SfChart Grid.Column="0">
<chart:SfChart.Annotations>
<chart:HorizontalLineAnnotation Y1="{Binding Y1}"
Stroke="Black"
StrokeThickness="2"
Text="Target"
.....>
</chart:HorizontalLineAnnotation>
</chart:SfChart.Annotations>
</chart:SfChart>
C#
internal class ViewModel : INotifyPropertyChanged
{
private double y1;
public double Y1
{
get => y1;
set
{
if(y1 != value)
{
y1 = value;
OnPropertyChanged(nameof(Y1));
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
.....
public ViewModel()
{
Y1 = 12000;
.....
}
}
Step 4: The second column of the grid layout contains a StackPanel with a Slider, TextBox and TextBlock, allowing the user to change the annotation value dynamically. The TextBox_TextChanged event ensures valid input by clamping values between 0 and the maximum of the Y_Axis.
XAML
<StackPanel Orientation="Vertical" Margin="10" Grid.Column="1">
<TextBlock Text="Adjust Target Line" FontSize="16" FontWeight="Bold" TextAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,20"/>
<TextBox Text="{Binding Y1}" HorizontalAlignment="Stretch" VerticalAlignment="Center" TextChanged="TextBox_TextChanged" Margin="0,0,0,20" Padding="10"/>
<Slider Minimum="{Binding Minimum, Source={x:Reference Y_Axis}}"
Maximum="{Binding Maximum, Source={x:Reference Y_Axis}}"
Value="{Binding Y1}" HorizontalAlignment="Stretch"/>
</StackPanel>
This code handles the TextChanged event for a TextBox, dynamically updating the Y1 property in the ViewModel while ensuring the value stays within the axis’s maximum and minimum bounds. It also manages text formatting and prevents recursive event triggers.
C#
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (Y_Axis == null) return;
var maxValue = Y_Axis.Maximum;
if (sender is TextBox textBox)
{
textBox.TextChanged -= TextBox_TextChanged;
if (string.IsNullOrWhiteSpace(textBox.Text))
{
viewModel.Y1 = double.MinValue;
textBox.Text = string.Empty;
}
else
{
if (int.TryParse(textBox.Text, out int newValue))
{
if (newValue > maxValue)
newValue = (int)maxValue;
else if (newValue < 0)
newValue = 0;
viewModel.Y1 = newValue;
textBox.Text = newValue.ToString();
textBox.CaretIndex = textBox.Text.Length;
}
else
{
textBox.Text = ((int)viewModel.Y1).ToString();
textBox.CaretIndex = textBox.Text.Length;
}
}
textBox.TextChanged += TextBox_TextChanged;
}
}
Step 5: This code defines a HorizontalLineAnnotation for a SfChart, representing a horizontal line at a specified Y-axis value. It includes custom styling such as dashed stroke, text with font formatting, and text alignment settings.
XAML
<chart:SfChart Grid.Column="0">
.....
<chart:SfChart.Annotations>
<chart:HorizontalLineAnnotation Y1="{Binding Y1}"
Stroke="Black"
StrokeThickness="2"
StrokeDashArray="5,2,2"
Text="Target"
FontSize="14"
FontWeight="Bold"
HorizontalTextAlignment="Left"
VerticalTextAlignment="Top">
</chart:HorizontalLineAnnotation>
</chart:SfChart.Annotations>
.....
</chart:SfChart>
Output:
You can find the complete sample from this GitHub Repo link.
Conclusion:
I hope you enjoyed learning about how to create and dynamically update target line for WPF Chart.
You can refer to our WPF Presentation feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. You can also explore our WPF Chart example to understand how to create and manipulate data.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.
If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!