We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Updating SfChart from the while loop

Hello,

In my application I'm updating the chart from the while loop, so I see the graph line after loop ending only. 
How can I see an each point?
Here is my code:

XAML:

<Window x:Class="Chart130085.MainWindow"
        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:chart="http://schemas.syncfusion.com/wpf"
        xmlns:local="clr-namespace:Chart130085"
        mc:Ignorable="d" WindowState="Maximized"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Name="btnStep" Click="btnStep_Click" Content="Next step" Width="60" Height="30"/>
        <chart:SfChart x:Name="myChart" Grid.Row="1" >
            <chart:SfChart.Header>
                <TextBlock Text="Chart output"/>
            </chart:SfChart.Header>
            <chart:SfChart.DataContext>
                <local:ChartPoints x:Name="T1"/>
            </chart:SfChart.DataContext>
            <chart:SfChart.PrimaryAxis>
                <chart:NumericalAxis 
            EnableScrollBarResizing="False" EnableTouchMode="False" 
            x:Name="Chart1_XAxis" Header="Frequency [MHz]" 
            LabelFormat=""  EdgeLabelsDrawingMode="Fit" />
            </chart:SfChart.PrimaryAxis>

            <chart:SfChart.SecondaryAxis>
                <chart:NumericalAxis x:Name="Chart1_YAxis" 
            Header="Amplitude" >
                </chart:NumericalAxis>
            </chart:SfChart.SecondaryAxis>

            <chart:SplineSeries StrokeThickness="2" x:Name="Chart1_Series1" 
        Label="Platinum" ItemsSource="{Binding FoundFrequencies}" 
        XBindingPath="Frequency" YBindingPath="Amplitude" Background="LightCyan"/>

            <chart:LineSeries ItemsSource="{Binding UnfoundFrequencies}"
              XBindingPath="Frequency" Interior="Red"
              YBindingPath="Amplitude"/>

            <chart:SfChart.Annotations>
                <chart:RectangleAnnotation x:Name="Chart1_PossibleRange"/>
            </chart:SfChart.Annotations>
        </chart:SfChart>

    </Grid>
</Window>


C# code:

using System;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

using System.Timers;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;


namespace Chart130085

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        

        public MainWindow()

        {

            InitializeComponent();

            freq = startFreq;

        }


        

        const double startFreq = 200;

        const double stepFreq = 10;

        const double stopFreq = 560;


        double freq = 0;


        

        public void updateGraph(double freq, double amp)

        {

            

            if(freq %40 == 0 && freq != startFreq)

            {

                T1.FoundFrequencies.Add(new ChartPoint { Frequency = freq, Amplitude = 0 });

                T1.FoundFrequencies.Add(new ChartPoint { Frequency = freq + stepFreq, Amplitude = 0 });

                T1.UnfoundFrequencies.Add(new ChartPoint { Frequency = freq, Amplitude = 0 });

                T1.UnfoundFrequencies.Add(new ChartPoint { Frequency = freq + stepFreq, Amplitude = 0 });

            }

            else

            {

                T1.FoundFrequencies.Add(new ChartPoint { Frequency = freq, Amplitude = amp });

                T1.FoundFrequencies.Add(new ChartPoint { Frequency = freq + stepFreq, Amplitude = amp });

                T1.UnfoundFrequencies.Add(new ChartPoint { Frequency = freq, Amplitude = double.NaN });

                T1.UnfoundFrequencies.Add(new ChartPoint { Frequency = freq + stepFreq, Amplitude = double.NaN });

            }

        }


        private void btnStep_Click(object sender, RoutedEventArgs e)

        {


            while (freq <= stopFreq)

            {

                double amp = freq * 3 / 12;

                updateGraph(freq, amp);

                Thread.Sleep(500);

                freq += stepFreq;

            }


        }

    }


    

    public class ChartPoint

    {

        public double Frequency { get; set; }

        public double Amplitude { get; set; }

    }




    public class ChartPoints

    {

        public ObservableCollection<ChartPoint> FoundFrequencies { get; set; } 

        public ObservableCollection<ChartPoint> UnfoundFrequencies { get; set; }


        public void Clear()

        {

            FoundFrequencies.Clear();

            UnfoundFrequencies.Clear();

        }


        public ChartPoints()

        {

            FoundFrequencies = new ObservableCollection<ChartPoint>();

            UnfoundFrequencies = new ObservableCollection<ChartPoint>();

        }

    }


}


The application is starting to work after click on the "Next Step" button.

Thank you a lot!!

11 Replies

DA Devi Aruna Maharasi Murugan Syncfusion Team April 27, 2017 02:14 PM UTC

Hi Michael, 
  
Thanks for contacting Syncfusion Support. 
  
We have analyzed your requirement and in order to view the data points of every update you can use DispatcherTimer rather than using While loop. 
  
Please find the code snippet 
public partial class MainWindow : Window 
    { 
        DispatcherTimer timer; 
        public MainWindow() 
        { 
            InitializeComponent(); 
            timer = new DispatcherTimer(); 
            timer.Interval = new TimeSpan(0, 0, 0, 0, 500); 
            timer.Tick += Timer_Tick; 
        } 
 
        private void Timer_Tick(object sender, EventArgs e) 
        { 
            if(freq <= stopFreq) 
            { 
                double amp = freq * 3 / 12; 
                updateGraph(freq, amp); 
                freq += stepFreq; 
            } 
 
        } 
 
 
        private void btnStep_Click(object sender, RoutedEventArgs e) 
 
        { 
            timer.Start(); 
        } 
    } 
  
In the button Click event, we have start the to update the tick for every 500ms. 
  
We have prepared a demo sample for your reference and it can be downloaded from below link, 
  
  
Regards, 
Devi 






MI Michael April 27, 2017 02:36 PM UTC

Hello,
I cannot use timers, because I perform calculations each while loop iteration. Results of each calculation I need to present on the chart.
May be you could suggest me some another way to do it?
Thanks a lot!


DA Devi Aruna Maharasi Murugan Syncfusion Team April 28, 2017 10:17 AM UTC

Hi Michael, 
  
Thanks for your update. 
  
you can view the updated data points added in the collection by delaying the Task instead of using Thread.Sleep() in while loop. 
  
Since Thread.Sleep() blocks the current thread for provided time, we can delay the corresponding task for provided times with Task.Delay. 
  
Please find the code snippet, 
private async void btnStep_Click(object sender, RoutedEventArgs e) 
  { 
     while(freq <= stopFreq) 
       { 
           double amp = freq * 3 / 12; 
           updateGraph(freq, amp); 
           await Task.Delay(500); 
           freq += stepFreq; 
             
       } 
  } 
 
  
We have modified the sample and it can be downloaded from below link, 
  
  
Regards, 
Devi 
 



MI Michael April 30, 2017 12:07 PM UTC

Hello,
I think it's not a solution that I'm searching for... I'll try to explain more:
1. My application requesting the data from specific place 40-50 times.
2. On each data receive I need to perform some calculations and to present the calculated point on the graph.
The pseudo code looks like:

while(nofRequest <40)
{
    data = getData()
    point = calculatePoint(data)
    chartDataContextModel.AddPoint(point)
    //here graph should be updated and should present the new point to the user, but it's not happening 
    nofRequest ++
}

Please, your advice.

Thanks a lot!


SA Santhiya Arulsamy Syncfusion Team May 1, 2017 01:45 PM UTC

Hi Michael,

Thanks for the update.

We have modified the sample and we are unable to reproduce the problem. Could you please reproduce the problem in the attached sample? This will be helpful for us to provide a proper solution.

Sample: ItemsSource130177


Thanks,
Santhiya A


MI Michael May 4, 2017 09:17 AM UTC

Hello,
Thanks a lot for your help!
The real application looks like so:

bool findPointInAmplitude(double frequency, ref foundAmp)
{
     double startAmp = 0;
     double endAmp = 20;
     const double stepAmp = 0.2;
     bool pointFound = false;
     while(endAmp - startAmp >= stepAmp)
    {
            double meanAmp = ( endAmp + startAmp ) / 2;
            setSinusToRemoteMachine(frequency, meanAmp);

            //wait 300 ms minimum !!!

            int status = getStatusFromRemoteMachine();
            if(status == 1)
           {
                endAmp = meanAmp;
                pointFound = true;
           }
           else
          {
               startAmp = meanAmp;
          }
    }
    if(pointFound )
    {
          foundAmp = endAmp;
    }
    
    return pointFound;
}

void mainFunc()
{
     for(int i=0; i<frequencies.Count; i++)
    {
           double foundAmp=0;
           bool isPointFound = findPointInAmplitude(frequencies[i], ref foundAmp);
           if(isPointFound)
          {
               (Chart1_Series1.ItemsSource as ObservableCollection<ChartPoint>).Add(new ChartPoint() { Frequency = frequencies[i], Amplitude = foundAmp });
               (Chart1_Series2.ItemsSource as ObservableCollection<ChartPoint>).Add(new ChartPoint() { Frequency = frequencies[i], Amplitude = double.NaN });
          }
          else
          {
               (Chart1_Series1.ItemsSource as ObservableCollection<ChartPoint>).Add(new ChartPoint() { Frequency = frequencies[i], Amplitude = double.NaN});
               (Chart1_Series2.ItemsSource as ObservableCollection<ChartPoint>).Add(new ChartPoint() { Frequency = frequencies[i], Amplitude = 0 });
          }
     }
}

In this case I need to show the new points on the graph at the realtime. Each point in time.

Thank you very much!!!


DA Devi Aruna Maharasi Murugan Syncfusion Team May 5, 2017 09:58 AM UTC

Hi Michael, 
  
Thanks for your update. 
  
As we mentioned in our earlier update, we can view the each updated data points in realtime by delaying the Task with Task.Delay() as shown in below code.  
 
async void mainFunc() 
        { 
            for (int i = 0; i < frequencies.Count; i++) 
            { 
                 
             } 
             await Task.Delay(500); 
         } 
 
  
We have prepared the demo sample to view the update of each data point in real time with the reference of provided code. 
  
The sample can be downloaded from below link, 
  
Sample: RealTime130177 
  
Regards, 
Devi 






MI Michael May 8, 2017 08:53 AM UTC

Hello,
The problem that I need to update charts synchronously, in the same thread where I get values from the device.
In another thread (Main thread) I need to give to the user possibility to control the GUI (like stop/pause the test and etc.).
In WinForms for the same task I used the timer to get new values and to sync with a main GUI where charts were placed. I thought that in WPF it should be more easy, but I see that it's not. Am I wrong?
Thanks a lot!  


SA Santhiya Arulsamy Syncfusion Team May 9, 2017 02:13 PM UTC

Hi Michael,

Thanks for the update.

When we adding the data points to the chart ItemsSource from the loop, we need to set some delay to render the points. WPF controls like ListView also need some delay to render items while adding the items from the loop. Could you please tell us our previous solution is resolved your problem? If not please share the simple sample to reproduce the problem.

We have modified the sample by using the ListView. Please find the sample from the following location.
 
 
Sample: RealTime130177
 
 
Thanks, 
Santhiya A 
 



MI Michael May 9, 2017 02:53 PM UTC

Thanks!
I use the IProgress method to update the collection.
Thank you a lot!


DA Devi Aruna Maharasi Murugan Syncfusion Team May 10, 2017 12:10 PM UTC

Hi Michael, 
  
Thanks for your update. 
  
We are glad to hear that your problem has been resolved. Please let us know, if you need any further assistance on this. 
  
Regards, 
Devi 


Loader.
Up arrow icon