Introduction
Microsoft Chart Controls is a charting component provided by Microsoft for ASP.NET and Windows Forms applications under .NET Framework 3.5 SP1. While numerous tutorials exist demonstrating its use in ASP.NET and Windows Forms environments, this article explores a different approach: implementing Microsoft Chart Controls with in WPF applications.
Prerequisites
Before beginning, you must download and install Microsoft Chart Controls from the Microsoft website. The following packages are required:
- Microsoft Chart Controls for Microsoft .NET Framework 3.5 - The primary installation package
- Microsoft Chart Controls for Microsoft .NET Framework 3.5 Language Pack - Localized text resources including error messages, available in 23 languages
- Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008 - Provides Visual Studio 2008 toolbox integration and IntelliSense support
Implementation Steps
Creating a WPF Application
Start by creating a new WPF application project in Visual Studio.
Adding Required DLL References
Add the following three DLL references to your project:
C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll- Windows Presentation Foundation WindowsForms Integration LibraryC:\Program Files\Microsoft Chart Controls\Assemblies\System.Windows.Forms.DataVisualization.dll- Microsoft Chart Controls DLLSystem.Windows.Forms.dll- Windows Forms base library
Add the following namespace declarations to your XAML file:
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:chr="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
Creating the XAML Layout
WPF cannot directly host Windows Forms controls. The WindowsFormHost element, along with the Forms integration DLL, enables embedding Windows Forms components within WPF.
<Grid>
<wfi:WindowsFormHost x:Name="chartHost">
<chr:Chart x:Name="performanceChart"/>
</wfi:WindowsFormHost>
</Grid>
Backend Code Implementation
The following code creates a real-time CPU usage monitoring chart that updates every second. This implementation uses a DataTable to store performance data and dynamically updates the chart display.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Data;
using System.Windows.Threading;
using System.Diagnostics;
using System.Windows.Forms.DataVisualization.Charting;
namespace WpfChartDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private DataTable metricsTable = new DataTable();
private PerformanceCounter cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += Timer_Tick;
timer.Interval = TimeSpan.FromSeconds(1);
timer.Start();
InitializeDataTable();
ConfigureChart();
this.performanceChart.DataSource = metricsTable;
this.performanceChart.DataBind();
}
private void InitializeDataTable()
{
metricsTable.Columns.Add("CPU_Usage", typeof(double));
metricsTable.Columns.Add("Memory_Usage", typeof(double));
for (int i = 0; i < 30; i++)
{
DataRow row = metricsTable.NewRow();
row["CPU_Usage"] = 0.0;
metricsTable.Rows.Add(row);
}
}
private void ConfigureChart()
{
ChartArea chartRegion = new ChartArea("PrimaryRegion");
chartRegion.Area3DStyle.Enable3D = true;
this.performanceChart.ChartAreas.Add(chartRegion);
Legend cpuLegend = new Legend("CPU_Legend");
cpuLegend.IsTextAutoFit = true;
cpuLegend.Docking = Docking.Bottom;
this.performanceChart.Legends.Add(cpuLegend);
Series cpuSeries = new Series("CPU_Series");
cpuSeries.ChartArea = "PrimaryRegion";
cpuSeries.ChartType = SeriesChartType.Line;
cpuSeries.IsVisibleInLegend = true;
cpuSeries.Legend = "CPU_Legend";
cpuSeries.LegendText = "CPU Utilization";
cpuSeries.YValueMembers = "CPU_Usage";
this.performanceChart.Series.Add(cpuSeries);
}
private void Timer_Tick(object sender, EventArgs e)
{
if (metricsTable.Rows.Count > 30)
{
metricsTable.Rows.RemoveAt(0);
}
DataRow newRow = metricsTable.NewRow();
newRow["CPU_Usage"] = cpuCounter.NextValue();
metricsTable.Rows.Add(newRow);
this.performanceChart.DataBind();
CommandManager.InvalidateRequerySuggested();
}
}
}
How It Works
The implementation uses a DispatcherTimer to trigger updates every second. Each tick retrieves the current CPU utilization percentage using the PerformanceCounter class and adds it to the DataTable. The chart maintains a rolling window of 30 data points, removing the oldest entry when the limit is exceeded.
The WindowsFormHost element serves as the bridge between WPF and Windows Forms, allowing the Chart control to be embedded seamlessly within the WPF layout. The chart is configured with 3D styling and includes a legend positioned at the bottom of the chart area.
References
- DOT.Developer - Microsoft Chart Controls in a WPF application
- Jeff's Blog - MSChart Basic Usage for Performance Counter Interface