Profile Picture

Correct Method to bind chart to view model

Posted By Thomas Ulrich 9 Years Ago
Author
Message
Thomas Ulrich
Posted 9 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)

Group: Forum Members
Last Active: 9 Years Ago
Posts: 2, Visits: 20
I am trying to access the chart object created in the mainwindow.xaml file within my viewmodel file. The code I have included is for a simple program I made that uses a basic PID controller and graphs the output using an opensource charting tool called oxyplot (won't work for the speed I need for updating the plots and it bogs down my UI). The implementation is the same as what I have come across in some other charting tools as well (in terms of accessing the chart object from within the view model instead of from maindwindow.cs.

In the example code I included below, PlotModel is the reference I am able to bind to the chart object so that I can access it through the view model called MainViewModel.cs. I tried to reference the Nchartcontrol object in the same manner but I am only able to do that if I use it in Mainwindow.cs (I receive an error that the variable does exist within the current context). I have not been able to access it from MainViewModel.cs. Is there a property associated with an Nchartcontrol that allows me to access it within the viewmodel similar to the oxyplot model property I bound the chart control to in the sample below? I tried changing the datacontext away from mainwindow to the viewmodel, but that caused several errors. I am fairly new to wpf so I am probably missing something simple, but it is beyond me. Hopefully, this is enough information, but if that isn't clear enough let me know and I would be happy to provide more detail.

Thanks! 

Mainwindow.xaml

<Window x:Class="PID_Charted.MainWindow"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:oxy="http://oxyplot.org/wpf"
   xmlns:local="clr-namespaceTongueID_Charted"
   Title="PID Dynamic Chart Update Example" Height="600" Width="750">
  <window.DataContext>
   <local:MainViewModel/>
  </window.DataContext>

  <Grid>
   <Grid.RowDefinitions>
    <RowDefinition Height="400"/>
    <RowDefinition/>
   </Grid.RowDefinitions>

   <oxyTonguelotView Model="{Binding DataPlot}" Title="{Binding Title}">
    <oxyTonguelotView.Axes>
      <oxy:LinearAxis IsAxisVisible="False"/>
    </oxyTonguelotView.Axes>
    <oxyTonguelotView.Series>
      <oxy:LineSeries ItemsSource="{Binding Points}"/>
    </oxyTonguelotView.Series>

   </oxyTonguelotView>
   <Label VerticalAlignment="Bottom" Grid.Row="2" Content="{Binding SimRunTime, Mode=Default}"/>
  </Grid>
</Window>

MainViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OxyPlot;
using OxyPlot.Series;
using System.Windows.Threading;
using OxyPlot.Axes;
using System.Diagnostics;
using System.ComponentModel;

namespace PID_Charted
{
  public class MainViewModel : INotifyPropertyChanged
  {
   //PID Variables
   double Last_PV, PV;
   double Last_MV, MV;
   double Error, LError, IError, DError;
   double Setpoint;
   double Kp = 1, Ki = 1, Kd = 1;

   public PlotModel DataPlot { get; set; }

   LinearAxis xAxis;
   LinearAxis yAxis;

   //Timer
   DispatcherTimer timer = new DispatcherTimer();
   private int _xValue = 1;

   Stopwatch StopWatch = new Stopwatch();

   public MainViewModel()
   {
    Setpoint = 100;
    Last_PV = 0;
    Last_MV = 0;
    LError = 0;

    DataPlot = new PlotModel();

    // now let's define X and Y axis for the plot model

    xAxis = new LinearAxis();
    xAxis.Position = AxisPosition.Bottom;
    xAxis.Title = "Time (s)";
    xAxis.MajorStep = 50;

    yAxis = new LinearAxis();
    yAxis.Position = AxisPosition.Left;
    yAxis.Maximum = 150;
    yAxis.Minimum = 0;

    yAxis.Title = "Values";

    DataPlot.Axes.Add(xAxis);
    DataPlot.Axes.Add(yAxis);


    DataPlot.Title = "PID";
    DataPlot.Series.Add(new LineSeries());
    DataPlot.Series.Add(new LineSeries());

    
    timer.Tick += new EventHandler(Update);
    timer.Interval = new TimeSpan(0, 0, 0, 0, 30);
    timer.Start();
    StopWatch.Start();
   }

   private int _SimRunTime;

   public int SimRunTime
   {
    get
    {
      return _SimRunTime;
    }
    set
    {
      _SimRunTime = value;
      OnPropertyChanged("SimRunTime");
    }
   }

   public void Update(object sender, EventArgs e)
   {
    SimRunTime = (int)StopWatch.Elapsed.TotalSeconds;
    
    //WTF????
    int timering = ((int)StopWatch.ElapsedMilliseconds);

    Setpoint_Setter();
    PID();
    Process();

    //if (SimTicker % 10 == 0)
    {
      Dispatcher.CurrentDispatcher.Invoke(() =>
      {

        (DataPlot.Series[1] as LineSeries).Points.Add(new DataPoint(timering, Setpoint));
        (DataPlot.Series[0] as LineSeries).Points.Add(new DataPoint(timering, Last_PV));
        if ((DataPlot.Series[0] as LineSeries).Points.Count > 100) //show only n last points
        {
          (DataPlot.Series[0] as LineSeries).Points.RemoveAt(0); //remove first point
          (DataPlot.Series[1] as LineSeries).Points.RemoveAt(0);
        }
        //if you don't want to have the graph resize on the x axis as it starts off
        //if (_xValue < 100)
        //{
        //  xAxis.Minimum = 0;
        //  xAxis.Maximum = 100;
        //}
        //else
        //{
        //  xAxis.Minimum = _xValue - 100;
        //  xAxis.Maximum = _xValue;
        //}
        xAxis.IsAxisVisible = false;
        DataPlot.InvalidatePlot(true);
      

       _xValue++;
      });
    }
   }

   //PID Controller
   //http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/
   public void PID()
   {
    Error = Setpoint - Last_PV;
    IError += Error;
    DError = Error - LError;
    LError = Error;

    Last_MV = Kp * Error + Ki * IError + Kd * DError;
    if (Last_MV > 150)
    {
      Last_MV = 150;
    }

    if (Last_MV < 5)
    {
      Last_MV = 5;
    }
   }

   public void Process()
   {
    Last_PV += (Last_MV - Last_PV) / 30;
   }

   public void Setpoint_Setter()
   {
    if (_SimRunTime < 40)
      Setpoint = 100;
    if (_SimRunTime >= 40)
      Setpoint = 50;
   }

   #region INotifyPropertyChanged Members

   public event PropertyChangedEventHandler PropertyChanged;

   private void OnPropertyChanged(string propertyName)
   {
    PropertyChangedEventHandler handler = PropertyChanged;

    if (handler != null)
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
   }

   #endregion

  }
}





Nevron Support
Posted 9 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)

Group: Forum Members
Last Active: Yesterday @ 1:54 AM
Posts: 3,054, Visits: 4,009
Hi,
Can you please send a simple application that demonstrates what you are trying to achieve.



Best Regards,
Nevron Support Team



Thomas Ulrich
Question Posted 9 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)

Group: Forum Members
Last Active: 9 Years Ago
Posts: 2, Visits: 20
The example listed in the user guide under getting started -> integrating with wpf section of the documentation demonstrates how to add a nevron chart to a visual studio project, however this example only covers how to implement the chart using the name property of the chart control and then referencing this name when setting up the chart and populating it with data in maindwindow.cs. I am trying to incorporate this with a view model and I am baffled I cannot get this to work. With other charting products I was able to create an instance of the chart control in my view model set all my parameters, populate with data, and then bind this instance of the chart control to the view through simple xaml binding. I assume most people are also working with view models, so what is recommended method for binding the chart control to the data I am generating in my model and exposing through my view model to the actual view? It seems like something very simple I am overlooking.




Similar Topics


Reading This Topic