Search code examples
c#wpfxamllivecharts

How to integrate custom tooltips into line chart in LiveCharts


References

  1. To produce line chart: https://lvcharts.net/App/examples/v1/Wpf/Line
  2. To produce tooltip: https://lvcharts.net/App/examples/v1/Wpf/Tooltips%20and%20Legends

What I want to do

I want to make a custom tooltip like the like the bar example in Reference 2, but in Reference 1

What I did

I copy pasted the tooltip in Reference 2, changed it to accommodate different variables

What went wrong

Tooltip on displays up to the box color, no variable values are shown.

Grey box with words expected, but only grey box shows up.

My Code

For both xaml and xaml.cs data for MainWindow, and Tooltip (called HITooltop)

MainWindow.xaml

<UserControl x:Class="NeoSpace.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:NeoSpace"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <lvc:CartesianChart Series="{Binding SeriesCollection}" LegendLocation="Right" >
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Sales" LabelFormatter="{Binding YFormatter}"></lvc:Axis>
            </lvc:CartesianChart.AxisY>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="Month" Labels="{Binding Labels}"></lvc:Axis>
            </lvc:CartesianChart.AxisX>
            <lvc:CartesianChart.DataTooltip>
                <local:HITooltip/>
            </lvc:CartesianChart.DataTooltip>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

MainWindow.xaml.cs

using System;
using System.Windows.Controls;
using LiveCharts;
using LiveCharts.Wpf;

namespace NeoSpace
{
    public partial class MainWindow : UserControl
    {
        public MainWindow()
        {
            InitializeComponent();
            GraphicOutput HI01 = new GraphicOutput("Device01", "01-02-03-40-50-12", "Idle", 
                new ChartValues<double> { 3, 6, 9, 12, 15 }, new ChartValues<double> { 3, 6, 9, 12, 15 });
            GraphicOutput HI02 = new GraphicOutput("Device02", "01-02-03-40-50-12", "Idle");
            GraphicOutput HI03 = new GraphicOutput(
                new ChartValues<double> { 5, 10, 15, 20, 25 }, new ChartValues<double> { 5, 10, 15, 20, 25 });
            SeriesCollection = new SeriesCollection
            {
                new LineSeries
                {
                    Title = HI01.Device,
                    Values = HI01.Thoroughput
                },
                new LineSeries
                {
                    Title = HI02.Device,
                    Values = HI02.Thoroughput,
                    PointGeometry = null
                },
                new LineSeries
                {
                    Title = HI03.Device,
                    Values = HI03.Thoroughput,
                    PointGeometry = DefaultGeometries.Square,
                    PointGeometrySize = 15
                }
            };

            Labels = new[] { "Time 01", "Time 02", "Time 03", "Time 04", "Time 05" };
            YFormatter = value => value.ToString();
            DataContext = this;
        }
        public SeriesCollection SeriesCollection { get; set; }
        public string[] Labels { get; set; }
        public Func<double, string> YFormatter { get; set; }
    }
}

HITooltip.xaml

<UserControl x:Class="NeoSpace.HITooltip"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpf="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             xmlns:local="clr-namespace:NeoSpace"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             d:DataContext="{d:DesignInstance local:HITooltip}"
             Background="#E4555555" Padding="20 10" BorderThickness="2" BorderBrush="Orange">
    <ItemsControl ItemsSource="{Binding Data.Points}" Grid.IsSharedSizeScope="True">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type wpf:DataPointViewModel}">
                <Grid Margin="2">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Device"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="BDAddress"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="State"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Thoroughput"/>
                    </Grid.ColumnDefinitions>
                    <Rectangle Grid.Column="0" Stroke="{Binding Series.Stroke}" Fill="{Binding Series.Fill}"
                               Height="15" Width="15"></Rectangle>
                    <TextBlock Grid.Column="1" Text="{Binding ChartPoint.Instance.(local:GraphicOutput.Device)}" 
                               Margin="5 0 0 0" VerticalAlignment="Center" Foreground="White"/>
                    <TextBlock Grid.Column="2" Text="{Binding ChartPoint.Instance.(local:GraphicOutput.BDAddress)}" 
                               Margin="5 0 0 0" VerticalAlignment="Center" Foreground="White"/>
                    <TextBlock Grid.Column="3" Text="{Binding ChartPoint.Instance.(local:GraphicOutput.State)}" 
                               Margin="5 0 0 0" VerticalAlignment="Center" Foreground="White"/>
                    <TextBlock Grid.Column="3" Text="{Binding ChartPoint.Instance.(local:GraphicOutput.Thoroughput)}" 
                               Margin="5 0 0 0" VerticalAlignment="Center" Foreground="White"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

HITooltip.xaml.cs

using System.ComponentModel;
using LiveCharts;
using LiveCharts.Wpf;

namespace NeoSpace
{
    public partial class HITooltip : IChartTooltip
    {
        private TooltipData _data;

        public HITooltip()
        {
            InitializeComponent();
            DataContext = this;
        }

        public TooltipData Data
        {
            get { return _data; }
            set
            {
                _data = value;
                OnPropertyChanged("TooltipData");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public TooltipSelectionMode? SelectionMode { get; set; }

        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            if (PropertyChanged != null)
            { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
        }
    }
}

The class GraphicOutput which is to be graphed and values revealed on the tooltip

using LiveCharts;

namespace NeoSpace
{
    public class GraphicOutput
    {
        public string Device { get; set; }
        public string BDAddress { get; set; }
        public string State { get; set; }
        public ChartValues<double> FrameSize { get; set; }
        public ChartValues<double> Thoroughput { get; set; }

        public GraphicOutput(string a, string b, string c, ChartValues<double> d1, ChartValues<double> d2)
        {
            Device = a;
            BDAddress = b;
            State = c;
            FrameSize = d1;
            Thoroughput = d2;
        }

        public GraphicOutput(string a, string b, string c)
        {
            Device = a;
            BDAddress = b;
            State = c;
            FrameSize = new ChartValues<double> { 1, 2, 3, 4, 5 };
            Thoroughput = new ChartValues<double> { 1, 2, 3, 4, 5 };
        }

        public GraphicOutput(ChartValues<double> d1, ChartValues<double> d2)
        {
            Device = "A Device";
            BDAddress = "11:22:33:44:55:66";
            State = "Too Idle";
            FrameSize = d1;
            Thoroughput = d2;
        }
    }
}


Solution

  • In HITooltip class the property name should be Data instead of TooltipData.

    public TooltipData Data
    {
        get { return _data; }
        set
        {
            _data = value;
            OnPropertyChanged("Data");
        }
    }