WPF: try to populate my chart with real time data

517 Views Asked by At

This is my model that calculate my network traffic rate:

public NetworkStatistics
{
     public static double trafficrate;

     public void start
     {
          trafficrate = ... // here my static variable gets all the rate
     }
}

This is my chart:

<chartingToolkit:Chart Name="lineChart" Margin="16,90,30,483" Background="Transparent">
            <chartingToolkit:LineSeries Name="chartSeries" 
                 ItemsSource="{Binding}" IsSelectionEnabled="True" Margin="0,-37,0,37" >
                <chartingToolkit:LineSeries.Template>
                    <ControlTemplate TargetType="chartingToolkit:LineSeries">
                        <Canvas x:Name="PlotArea">
                            <Polyline x:Name="polyline"
                                          Points="{TemplateBinding Points}" 
                                          Stroke="Yellow" 
                                          Style="{TemplateBinding PolylineStyle}" />
                        </Canvas>
                    </ControlTemplate>
                </chartingToolkit:LineSeries.Template>
            </chartingToolkit:LineSeries>
        </chartingToolkit:Chart>

In my application constructor i started my statistics start method and the value trafficrate start to get values.

This is my timer tick event that using it i want to populate my chart every one second:

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    double rate = NetworkStatistics.trafficrate;
    chartSeries.Points.Add(new Point(DateTime.Now, rate));
}

But nothing happen. BTW how can i only insert one value instead of Point that need 2 values ?

Edit

public MainWindow()
{
    InitializeComponent();

    points = new ObservableCollection<KeyValuePair<int, int>>();
    points.Add(new KeyValuePair<int, int>(1, 60));
    points.Add(new KeyValuePair<int, int>(2, 20));
    points.Add(new KeyValuePair<int, int>(3, 50));
    points.Add(new KeyValuePair<int, int>(4, 30));
    points.Add(new KeyValuePair<int, int>(5, 40));
    points.Add(new KeyValuePair<int, int>(6, 200));
    points.Add(new KeyValuePair<int, int>(7, 1));
    points.Add(new KeyValuePair<int, int>(8, 450));
    points.Add(new KeyValuePair<int, int>(4, 30));
    points.Add(new KeyValuePair<int, int>(5, 40));
    this.DataContext = this;

    CreateTimer();
}

    public void CreateTimer()
    {
        DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
        dispatcherTimer.Tick += dispatcherTimer_Tick;
        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 333);
        dispatcherTimer.Start();
    }

    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        int pos = 300;
        var r = new Random();
        for (int i = 0; i < 1000; i++)
        {
            points.Add(new KeyValuePair<int, int>(i, r.Next(1000)));
        }
    }

My XAML:

<Grid>
            <Grid.Resources>
                <Style x:Key="EmptyPointsStyle" TargetType="{x:Type chartingToolkit:LineDataPoint}">
                    <Setter Property="Template" Value="{x:Null}"/>
                </Style>

                <Style TargetType="{x:Type chartingToolkit:LineSeries}">
                    <Setter Property="DataPointStyle" Value="{StaticResource EmptyPointsStyle}"/>
                    <Setter Property="PolylineStyle">
                        <Setter.Value>
                            <Style TargetType="{x:Type Polyline}">
                                <Setter Property="StrokeThickness" Value="2"/>
                                <Setter Property="StrokeMiterLimit" Value="1"/>
                            </Style>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type chartingToolkit:LineSeries}">
                                <Canvas x:Name="PlotArea">
                                    <Polyline Stroke="{TemplateBinding BorderBrush}" Style="{TemplateBinding PolylineStyle}" Points="{TemplateBinding Points}"/>
                                </Canvas>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Grid.Resources>
            <chartingToolkit:Chart  Name="lineChart" Title="Line Series Demo" VerticalAlignment="Top" Margin="50" Height="254">
                <chartingToolkit:LineSeries  DependentValuePath="Value" IndependentValuePath="Key" ItemsSource="{Binding points}" IsSelectionEnabled="True"/>
            </chartingToolkit:Chart>
        </Grid>
1

There are 1 best solutions below

1
On

To work with the LineSeries and PolyLines i am using the following XAML:

<Window x:Class="WPFToolkitProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
    Title="MainWindow" Height="350" Width="525" Loaded="MainWindow_OnLoaded">
<Grid>
    <Grid.Resources>
        <Style x:Key="EmptyPointsStyle" TargetType="{x:Type chartingToolkit:LineDataPoint}">
            <Setter Property="Template" Value="{x:Null}"/>
        </Style>

        <Style TargetType="{x:Type chartingToolkit:LineSeries}">
            <Setter Property="DataPointStyle" Value="{StaticResource EmptyPointsStyle}"/>
            <Setter Property="PolylineStyle">
                <Setter.Value>
                    <Style TargetType="{x:Type Polyline}">
                        <Setter Property="StrokeThickness" Value="2"/>
                        <Setter Property="StrokeMiterLimit" Value="1"/>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type chartingToolkit:LineSeries}">
                        <Canvas x:Name="PlotArea">
                            <Polyline Stroke="{TemplateBinding BorderBrush}" Style="{TemplateBinding PolylineStyle}" Points="{TemplateBinding Points}"/>
                        </Canvas>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <chartingToolkit:Chart  Name="lineChart" Title="Line Series Demo" VerticalAlignment="Top" Margin="50" Height="254">
        <chartingToolkit:LineSeries  DependentValuePath="Value" IndependentValuePath="Key" ItemsSource="{Binding points}" IsSelectionEnabled="True"/>
    </chartingToolkit:Chart>
</Grid>

And here is code behind : public partial class MainWindow : Window { public ObservableCollection> points { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        points = new ObservableCollection<KeyValuePair<int, int>>();
        points.Add(new KeyValuePair<int, int>(1, 60));
        points.Add(new KeyValuePair<int, int>(2, 20));
        points.Add(new KeyValuePair<int, int>(3, 50));
        points.Add(new KeyValuePair<int, int>(4, 30));
        points.Add(new KeyValuePair<int, int>(5, 40));
        points.Add(new KeyValuePair<int, int>(6, 200));
        points.Add(new KeyValuePair<int, int>(7, 1));
        points.Add(new KeyValuePair<int, int>(8, 450));
        points.Add(new KeyValuePair<int, int>(4, 30));
        points.Add(new KeyValuePair<int, int>(5, 40));

        this.DataContext = this;
    }


    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        #region Adding points at runtime - test

        Task.Run(() =>
        {

            System.Threading.Thread.Sleep(5000);

            int pos = 300;
            var r = new Random();

            for (int i = 0; i < 1000; i++)
            {
                Dispatcher.Invoke(() =>
                {
                    points.Add(new KeyValuePair<int, int>(i, r.Next(1000)));

                });
                System.Threading.Thread.Sleep((100));
            }
        });

        #endregion Adding points at runtime - test
    }
}

The update works correctly, and the visual representation is fast enough in my opinion.