Technology evolves rapidly and it’s becoming increasingly difficult to differentiate when to use what tool. This blog post seeks to assist you in making a decision between using a reporting solution and when to build custom views with a control suite in your application. We will begin by reviewing criteria that outlines the strengths of each solution and dive into an example scenario using a control suite. In part two of this series, we will dive into a scenario where using a Reporting solution is beneficial.
It’s no mystery that a reporting solution is built with the purpose of data visualization, printing/archiving and data sharing at its core. Control suites on the other hand are built with user experience and interactivity in mind. Control suites do deal with data presentment, but also deal with data entry.
Let’s begin with reviewing features that reporting solutions and control suites perform equally well.
Some of the features where applying a control suite would be beneficial are:
The following features are where a reporting solution shines:
Before deciding which solution to use, you need to answer these questions:
Have you been in the position to answer similar questions? If yes, please share your experience in the comments below – I would love to hear them!
As mentioned above, it is best to use a control suite when you want to have real-time live data displays and dashboards. An example of a live data requirement can be a patient monitoring application. In this example, we used RadControls for WinForms to build a solution to demonstrate live updates of data into a RadChartView control. The control is responsible for displaying the heart rate and blood pressure values of a patient at 5 second intervals.
Figure 1 - A simulated real-time medical monitoring application
To implement this solution, first we will need to encapsulate the data being measured, a repository to retrieve the information from and lastly a Live Monitor that will access the repository for measurements every five seconds.
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
namespace GridsAndReporting
{
public class MedicalInfo : INotifyPropertyChanged
{
private DateTime _timeOfMeasurement;
private int _heartRate;
private int _systolicBloodPressure;
private int _diastolicBloodPressure;
public DateTime TimeOfMeasurement
{
get
{
return this ._timeOfMeasurement;
}
set
{
this ._timeOfMeasurement = value ;
OnPropertyChanged( "TimeOfMeasurement" );
}
}
public int HeartRate
{
get
{
return this ._heartRate;
}
set
{
this ._heartRate = value ;
OnPropertyChanged( "HeartRate" );
}
}
public int SystolicBloodPressure
{
get
{
return this ._systolicBloodPressure;
}
set
{
this ._systolicBloodPressure = value ;
OnPropertyChanged( "SystolicBloodPressure" );
}
}
public int DiastolicBloodPressure
{
get
{
return this ._diastolicBloodPressure;
}
set
{
this ._diastolicBloodPressure = value ;
OnPropertyChanged( "DiastolicBloodPressure" );
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged( string propertyName)
{
if (PropertyChanged != null )
{
PropertyChanged( this , new PropertyChangedEventArgs (propertyName));
}
}
}
public class LiveMonitor : INotifyPropertyChanged
{
private BindingList < MedicalInfo > _data;
private System.Windows.Forms. Timer _timer;
private MedicalInfoRepository _repo = new MedicalInfoRepository ();
public BindingList < MedicalInfo > Data
{
get
{
return this ._data;
}
set
{
this ._data = value ;
OnPropertyChanged( "Data" );
}
}
public LiveMonitor()
{
//start 5 second timer
_timer = new System.Windows.Forms. Timer ();
_timer.Interval = 5000;
_timer.Tick += _timer_Tick;
Data = _repo.RefreshMeasurements( DateTime .Now);
}
void _timer_Tick( object sender, EventArgs e)
{
Data = _repo.RefreshMeasurements( DateTime .Now);
}
public void StartMonitor()
{
_timer.Start();
}
public void StopMonitor()
{
_timer.Stop();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged( string propertyName)
{
if (PropertyChanged != null )
{
PropertyChanged( this , new PropertyChangedEventArgs (propertyName));
}
}
}
public class MedicalInfoRepository
{
private BindingList < MedicalInfo > _data = new BindingList < MedicalInfo >();
public BindingList < MedicalInfo > RefreshMeasurements( DateTime start)
{
//Generate Random Medical Data
_data.Clear();
for ( int i = 0; i <5; i++)
{
Thread .Sleep(5);
Random r = new Random ( DateTime .Now.Millisecond);
MedicalInfo toAdd = new MedicalInfo ();
toAdd.TimeOfMeasurement = start;
start = start.AddSeconds(1);
toAdd.HeartRate = r.Next(60, 100);
toAdd.SystolicBloodPressure = r.Next(110, 130);
toAdd.DiastolicBloodPressure = r.Next(70, 85);
_data.Add(toAdd);
}
return _data;
}
}
}
Figure 2 – MedicalInfo class, LiveMonitor and MedicalInfoRepository class listings
Next we will need to implement the user interface, ensure that you drag an instance of the RadChartView control onto the design surface of your form. In the code-behind of the form, also declare a private instance of the LiveMonitor class as follows:
private LiveMonitor _monitor = new LiveMonitor ();
Figure 3– Instantiating a LiveMonitor field in the Form code-behind
Now we will initialize the RadChartView, using the multi-axes feature of the control so that heart rate can be visualized with blood pressure all in the same chart. To do this, create a method in your form code-behind as follows:
public void InitializeChart()
{
DateTimeContinuousAxis timeAxis = new DateTimeContinuousAxis ();
timeAxis.MajorStepUnit = Telerik.Charting. TimeInterval .Second;
timeAxis.MajorStep = 1;
timeAxis.LabelFormat = "{0:hh:mm:ss}" ;
timeAxis.LabelRotationAngle = 310;
timeAxis.Title = "Time of Measurement" ;
LinearAxis hr = new LinearAxis ();
hr.MajorStep = 10;
hr.AxisType = Telerik.Charting. AxisType .Second;
hr.Title = "Heart Rate (beats per minute)" ;
LinearAxis bp = new LinearAxis ();
bp.MajorStep = 25;
bp.AxisType = Telerik.Charting. AxisType .Second;
bp.HorizontalLocation = Telerik.Charting. AxisHorizontalLocation .Right;
bp.Title = "Blood Pressure (mm Hg)" ;
//first series, heart rate
LineSeries heartRate = new LineSeries ();
heartRate.LegendTitle = "Heart Rate" ;
heartRate.ValueMember = "HeartRate" ;
heartRate.CategoryMember = "TimeOfMeasurement" ;
heartRate.VerticalAxis = hr;
heartRate.HorizontalAxis = timeAxis;
heartRate.DataSource = _monitor.Data;
BarSeries systolic = new BarSeries ();
systolic.LegendTitle = "Systolic Blood Pressure" ;
systolic.ValueMember = "SystolicBloodPressure" ;
systolic.CategoryMember = "TimeOfMeasurement" ;
systolic.VerticalAxis = bp;
systolic.HorizontalAxis = timeAxis;
systolic.DataSource = _monitor.Data;
BarSeries diastolic = new BarSeries ();
diastolic.LegendTitle = "Diastolic BloodPressure" ;
diastolic.ValueMember = "DiastolicBloodPressure" ;
diastolic.CategoryMember = "TimeOfMeasurement" ;
diastolic.VerticalAxis = bp;
diastolic.HorizontalAxis = timeAxis;
diastolic.DataSource = _monitor.Data;
this .radChartView1.ShowLegend = true ;
this .radChartView1.Series.Add(heartRate);
this .radChartView1.Series.Add(systolic);
this .radChartView1.Series.Add(diastolic);
this .radChartView1.Area.View.Palette = KnownPalette .Metro;
}
Figure 4 – Instantiating RadChartView for medical monitoring
The InitializeChart method defines each axis displayed in the chart, the x axis, the time axis, being the common axis. The left-hand y axis will measure the heart rate of the patient, and the right-hand y-axis is responsible for measuring the systolic and diastolic blood pressure of the patient. This method is also responsible for defining the series’ being displayed in the chart. The first series is a line graph for the heart rate, and the two bar series are responsible for displaying blood pressure data. Be sure to call the InitializeChart method in the Form constructor:
InitializeChart();
Figure 5 – Calling the InitializeChart method from within the Form constructor
The last thing we need to do to implement this example is to start and stop the Live Monitor. To do this implement the Load and Leave event handlers as follows:
private void Form1_Load( object sender, EventArgs e)
{
_monitor.StartMonitor();
}
private void Form1_Leave( object sender, EventArgs e)
{
_monitor.StopMonitor();
}
Figure 6 – Starting and Stopping the Live Monitor in the Form Load and Leave event handlers
When the application is run the chart will update every 5 seconds. Please note that this is strictly generated medical data, I’m sure that if this were a real person that they would have some significant health concerns!
From this scenario, you can see that real-time data feeds are much better served with a control suite solution. In the next blog post we will review a scenario where a Reporting solution should be used.
Carey Payette is a Senior Software Engineer with Trillium Innovations (a Solliance partner), an ASPInsider, a Progress Ninja, a Microsoft Certified Trainer and a Microsoft Azure MVP. Her primary focus is cloud integration and deployment for the web, mobile, big data, AI, machine learning and IoT spaces. Always eager to learn, she regularly tinkers with various sensors, microcontrollers, programming languages and frameworks. Carey is also a wife and mom to three fabulous boys.