WPF はじめての OxyPlot

## WPFはチャート難民？

本気でチャートを使いたい民は、グレープシティ、インフラジスティックス、[SciChart](https://www.scichart.com/licensing-scichart-wpf/)など有料コンポーネントを使うのか・・・？

さらっと公式HPを見た感じだと [LiveCharts.Wpf](https://www.nuget.org/packages/LiveCharts.Wpf/) が良さそうだったけど、**残念ながら .NET Core 3.1 に対応していない**

なので代わりに [OxyPlot.Wpf](https://www.nuget.org/packages/OxyPlot.Wpf/) をプロジェクトに導入する

### 成果物

本記事で掲載しているコードの元プロジェクト

https://github.com/t13801206/HelloOxyPlot

※ GitHubのほうは随時更新する予定

## WPFで[OxyPlot](https://oxyplot.github.io/)をつかう

（いろいろ調べている中で予感はしていたけど、ドキュメントの整備が行き届いていない）

プロジェクトを立ち上げたら以下 NuGet パッケージをインストールする

```powershell
Install-Package OxyPlot.Wpf
```

### とりあえずグラフを描いてみる

[Docs » Getting started » WPF](https://oxyplot.readthedocs.io/en/latest/getting-started/hello-wpf.html)

チュートリアルの通りにコピペして実行すると、緑色のコサインカーブが表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/d61c41d1-10d8-3aec-60a2-0310fd7b866e.png)

### グラフの細かいところを変更する

Qiita記事から部品取りしていくのが早い

記事|おすすめポイント
-|-
[[C#] oxyplotでグラフを書く1](https://qiita.com/tera1707/items/1070993f6bccac9770c9)|コードが長く載っているので、必要なところだけ取って使える
[【更新あり】OxyPlotでグラフを表示させる際にハマったことまとめ](https://qiita.com/YSRKEN/items/04cb879bf7f19cd1567c)|「おまけ」の章に、いろいろ細かい設定をする方法が載っている
[[C#] OxyPlot Tips集](https://qiita.com/laughter/items/422e25a6b3150a3199e7)|やりたいことごとに章分けされている

### [プロットを更新する](https://oxyplot.readthedocs.io/en/master/common-tasks/refresh-plot.html)

手順が3つ書かれているが、XAMLへ`PlotModel`をバインディングしている場合は、`PlotModel.Invalidate(true)`を呼べばグラフが更新される

#### Case1: グラフを書き換える

`Clear()`して、データを`Add`して、`InvalidPlot(true)`をする

```cs
MyModel1.Series.Clear();
MyModel1.Series.Add(new FunctionSeries(Math.Sin, 0, 10, 0.1, "sin(x)"));
MyModel1.InvalidatePlot(true);
```

![Animation4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/f2a371ab-9f12-3860-4f7c-99c6396da02d.gif)

##### Case1' グラフの上に別のグラフを描く

`Clear`しなかった場合は、既存のプロットに追加される

```cs
//MyModel1.Series.Clear();
MyModel1.Series.Add(new FunctionSeries(Math.Sin, 0, 10, 0.1, "sin(x)"));
MyModel1.InvalidatePlot(true);
```

![Animation5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/b08bbcc7-c0aa-db0f-edb7-96ce5eaa8339.gif)

#### Case2: グラフのプロットを追加する

すでにあるプロットにデータを追加していく
`PlotModel`のシリーズを別途保持（`_lineSeries`）しておいて、そこに`Add`する

```cs
var x = DateTime.Now.Second;
var y = new Random().Next(-100, 100);

_lineSeries.Points.Add(new DataPoint(x, y));

MyModel2.InvalidatePlot(true);
```

![Animation6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/33cf1cc8-f8df-3db4-6cd3-5984d09d24fd.gif)

#### Case3: モデルのデータをプロットする

データは`ViewModel`とは別にモデルで持っておきたい

```cs
MyModel3 = _plotModelHandler.Create();
_plotModelHandler.Update();

//----------------------------------
// Model
_model.Axes.Add(XAxis); // 軸の最大値などを設定している
_model.Series.Add(_series); // モデルがデータを保持している

internal void Update()
{
    var x = new Random().Next(0, 1023);
    var y = new Random().Next(0, 4065);
    _series.Points.Add(new DataPoint(x, y));

    _model.InvalidatePlot(true);
}
```

![Animation7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/78945f81-5e86-4c83-4c48-382f7b7303c9.gif)

## おわりに

凝ったことしなければ、シンプルで使いやすいライブラリだと思う

## 参考サイト

https://shikaku-sh.hatenablog.com/entry/oxyplot-simple-usage