はじめに
WPF で DrawingContext
を利用した描画処理を実装している時に、次の画面再描画時に纏めて処理を実行したいことがありました。
所謂 JavaScript の Window.requestAnimationFrame
的なことを WPF でしたいというお話です。
確認時のバージョン情報
-
.NET
: 8.0.204
CompositionTarget.Rendering
方法: CompositionTarget を使用したフレームの間隔ごとの描画 - WPF .NET Framework | Microsoft Learn
CompositionTarget
は、アプリケーションが描画される表示サーフェイスを表す静的クラスです。
アプリケーションのシーンが描画されるたびにRendering
イベントが発生します。
レンダリングフレームレートは、1 秒あたりのシーンの描画回数です。
WPF には描画プロセス中に実行される CompositionTarget.Rendering
イベントがあるようです。
JavaScript の Window.requestAnimationFrame
とは異なり、描画フレーム毎に実行されるイベントですが、コードによっては 1 度だけ実行されるようにすることもできそうです。
コード例
下記コードは、次の画面再描画時に 1 度だけ処理を実行するよう要求する RequestRendering
メソッドを記述してみた例です。
ちなみに CompositionTarget
は静的クラスのため、WPF アプリケーション内であれば何処でも記述できます。
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace Sandbox;
public partial class MainWindow : Window {
public MainWindow() => this.InitializeComponent();
private bool _isRenderingRequested;
// 次の画面再描画時で処理実行を要求します。
protected void RequestRendering() {
if(this._isRenderingRequested) { return; }
void OnRendering(object? sender, EventArgs e) {
// 再描画時に実行したい適当な処理:
Console.WriteLine("rendering.");
CompositionTarget.Rendering -= OnRendering;
this._isRenderingRequested = false;
}
this._isRenderingRequested = true;
CompositionTarget.Rendering += OnRendering;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
base.OnMouseLeftButtonDown(e);
// 画面再描画までに連続で要求しても、処理は 1 度だけ実行されます。
this.RequestRendering();
this.RequestRendering();
this.RequestRendering();
Console.WriteLine("requested.");
}
}
おわりに
こんなことをせずに XAML だけで解決できるならそれに越したことはないです(個人的な感想)。