이 Post 는 WPF, C# 에서 2D Chart 를 그릴 때 자주 사용되는 OxyPlot 의 기초적인 사용법을 설명 합니다.
랜덤 값으로 꺾은선 그래프를 그리고 Zoom 과 Pan 을 막거나 초기화 하는 방법 또한 설명합니다.
0. 실행 화면

OxyPlot 는 WPF 나 C# 에서 2D 차트를 그릴때 사용할 수 있는 유용한 차트 라이브러리 입니다.
무료에 오픈소스이며 다양한 차트를 지원합니다.
Nuget 에서 바로 설치 할 수 있으며 레퍼런스 또한 많은 편입니다.
다만 문서나 설명이 좀 부족한게 흠입니다.
사실 기본적인 사용법만 알아두면 나머지는 다 비슷합니다.
이번 Post 에서는 LineSeries 를 통해 기본적인 사용법을 알아봅니다.
1. 프로젝트에서 Nuget 패키지 관리자를 실행

프로젝트에서 Mouse 우클릭 하여 Nuget 패키지 관리 메뉴를 선택 합니다.
2. OxyPlot.Wpf 설치

Nuget 패키지 관리자에서 oxyplot 로 검색하고, 검색 결과에서 OxyPlot.Wpf 를 설치 합니다.
3. MainWindow.xaml
<Window x:Class="BlogDemo01.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:local="clr-namespace:BlogDemo01"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<oxy:PlotView x:Name="plotView"/>
<StackPanel Grid.Column="1">
<Button x:Name="btnTest00" Content="Test 00" Margin="10" Height="24"/>
</StackPanel>
</Grid>
</Window>
xmlns:local 아래 oxy 네임스페이스를 추가 합니다.
화면에 oxy:PlotView 를 추가 합니다.
4. MainWindow.xaml.cs – 생성자
Random random = new Random(Guid.NewGuid().GetHashCode() + DateTime.Now.Millisecond);
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
랜덤 데이터를 만들기 위해 Random 클래스를 초기화 합니다.
Loaded 이벤트에서 그래프를 그려주기 때문에 MainWindow 가 표시되었을 때 그래프는 바로 보이게 됩니다.
그래프를 그리는 방법만 알고 싶으시다면 주석 처리된 부분은 무시하시면 됩니다.
5. 그래프 그리기
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
plotView.Model = TwoLineSeries();
}
public PlotModel TwoLineSeries()
{
PlotModel plotModel = new PlotModel();
plotModel.Title = "Two LineSeries";
var xAxis = new LinearAxis();
xAxis.Position = AxisPosition.Bottom;
xAxis.Title = "X Axis";
// if you want to disable zooming and panning, uncomment the following lines
//linearAxis1.IsZoomEnabled = false;
//linearAxis1.IsPanEnabled = false;
plotModel.Axes.Add(xAxis);
var yAxis = new LinearAxis();
//linearAxis2.Position = AxisPosition.Left;
//linearAxis2.Position = AxisPosition.Right;
yAxis.Title = "Y Axis";
// if you want to disable zooming and panning, uncomment the following lines
//linearAxis2.IsZoomEnabled = false;
//linearAxis2.IsPanEnabled = false;
plotModel.Axes.Add(yAxis);
var lineSeries1 = new LineSeries();
lineSeries1.Title = "LineSeries 1";
lineSeries1.Color = OxyColors.Red;
var lineSeries2 = new LineSeries();
lineSeries2.Title = "LineSeries 2";
lineSeries2.Color = OxyColors.Blue;
// Generate random data points for the line series
for (int i = 0; i <= 100; i += 10)
{
double y1 = random.Next(0, 30);
double y2 = random.Next(-5, 20);
lineSeries1.Points.Add(new DataPoint(i, y1));
lineSeries2.Points.Add(new DataPoint(i, y2));
}
plotModel.Series.Add(lineSeries1);
plotModel.Series.Add(lineSeries2);
return plotModel;
}
선이 두 개 있는 꺾은 선 그래프를 그립니다.
값은 랜덤으로 생성 합니다.
첫 번째 Axis 에서 Position 을 정해주면 두 번째 Axis 는 나머지 가로나 세로로 들어가게 됩니다.
Zoom(확대, 축소) 이나 Pan(이동) 을 막고 싶다면 주석 된 부분을 해제하면 됩니다.
단순히 그래프 구현 부분은 여기까지 보시면 됩니다.
이 다음은 여담 입니다.
5. 그외 그래프 줌, 이동 초기화 관련 내용
사실 하다 보니 확대 축소 혹은 이동 후 초기화 기능이 없어 몇 가지 더 구현한 내용이 있습니다.
전체 소스를 보겠습니다.
public partial class MainWindow : Window
{
Random random = new Random(Guid.NewGuid().GetHashCode() + DateTime.Now.Millisecond);
double xMin, xMax, yMin, yMax = 0;
public MainWindow()
{
InitializeComponent();
plotView.MouseMove += PlotView_MouseMove;
plotView.KeyDown += PlotView_KeyDown;
btnTest00.Click += BtnTest00_Click;
this.Loaded += MainWindow_Loaded;
}
private void PlotView_MouseMove(object sender, MouseEventArgs e)
{
if (!plotView.IsFocused)
{
plotView.Focus();
}
}
private void PlotView_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
foreach(Axis axis in plotView.Model.Axes)
{
axis.Reset();
}
plotView.Model.InvalidatePlot(true);
}
}
private void CheckFirstPosition()
{
if(plotView.Model == null || plotView.Model.Axes.Count == 0)
{
return;
}
foreach(Axis axis in plotView.Model.Axes)
{
if(axis.Position == AxisPosition.Bottom)
{
xMin = axis.ActualMinimum;
xMax = axis.ActualMaximum;
}
else
{
yMin = axis.ActualMinimum;
yMax = axis.ActualMaximum;
}
}
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
BtnTest00_Click(sender, e);
}
private void BtnTest00_Click(object sender, RoutedEventArgs e)
{
plotView.Model = TwoLineSeries();
CheckFirstPosition();
}
public PlotModel TwoLineSeries()
{
PlotModel plotModel = new PlotModel();
plotModel.Title = "Two LineSeries";
var xAxis = new LinearAxis();
xAxis.Position = AxisPosition.Bottom;
xAxis.Title = "X Axis";
// if you want to disable zooming and panning, uncomment the following lines
//linearAxis1.IsZoomEnabled = false;
//linearAxis1.IsPanEnabled = false;
plotModel.Axes.Add(xAxis);
var yAxis = new LinearAxis();
//linearAxis2.Position = AxisPosition.Left;
//linearAxis2.Position = AxisPosition.Right;
yAxis.Title = "Y Axis";
// if you want to disable zooming and panning, uncomment the following lines
//linearAxis2.IsZoomEnabled = false;
//linearAxis2.IsPanEnabled = false;
plotModel.Axes.Add(yAxis);
var lineSeries1 = new LineSeries();
lineSeries1.Title = "LineSeries 1";
lineSeries1.Color = OxyColors.Red;
var lineSeries2 = new LineSeries();
lineSeries2.Title = "LineSeries 2";
lineSeries2.Color = OxyColors.Blue;
// Generate random data points for the line series
for (int i = 0; i <= 100; i += 10)
{
double y1 = random.Next(0, 30);
double y2 = random.Next(-5, 20);
lineSeries1.Points.Add(new DataPoint(i, y1));
lineSeries2.Points.Add(new DataPoint(i, y2));
}
plotModel.Series.Add(lineSeries1);
plotModel.Series.Add(lineSeries2);
return plotModel;
}
}
xMin, xMax, yMin, yMax 는 그래프를 Zoom(확대, 축소), 혹은 Pan(이동) 했을 때 초기 상태로 되돌리기 위한 값을 저장합니다.
MainWindow 가 표시되면 그래프가 표시 됩니다.
이때 마우스 휠을 사용하여 확대 축소도 되고 마우스 우클릭 버튼을 눌러 이동도 됩니다.
다만, 마우스 휠을 사용해 확대 축소를 한 후에 Esc 버튼을 눌러 줌 상태를 초기화 하려면 동작하지 않을 수 있습니다.
왜냐면, PlotView 가 선택되지 않은 상태이기 때문에 Focus 가 없어 KeyDown 이벤트를 받을 수 없기 때문입니다.
이 때문에 MouseMove 이벤트에서는 그래프에서 Mouse 가 움직였을 경우 그래프에 Focus 를 줍니다.
또한 KeyDown 이벤트 에서는 Esc 키를 감지하여 Zoom 과 Pan 을 초기화 합니다.
6. OxyPlot 예제 프로젝트
여기까지 PxyPlot 를 사용하여 기본적인 그래프를 구현하는 방법을 확인 했습니다.
OxyPlot 에는 여러가지 그래프가 있지만 사용 방법은 다 비슷합니다.
OxyPlot 의 예제 프로젝트를 실행해 보시면 쉽게 확인 하실 수 있을 것 같습니다.
다음은 예제 프로젝트 실행 화면 입니다.
