LoginSignup
3
3

More than 1 year has passed since last update.

.NET MAUI RC3を試してみる(後編)

Last updated at Posted at 2022-06-01

.NET MAUIアプリについて「前編」でコンパイル、「中編」でサンプルコードのチェックをしました。今回は簡単なアプリを作って、レイアウトパネルの描画性能をWPFと比較してみます。

サンプル

ボールが飛び跳ねる様子を描画し、どれくらいのボール数まで耐えられるかを見てみます。
下の画像はWPFでボール100個を描画した場合です。アップロードサイズの都合で 15fps の画像ですが実際はもっとスムースに動きます。
アニメーションGIF版
mp4版

描画方法

絶対位置指定のできるレイアウトパネルにボール(Ellipse)を大量描画します。WPFは Canvas 、 MAUI は AbusoluteLayout を使いました。
ボールはアニメーション機能を使わず、フレーム描画イベントごとに自前描写、位置を v = v0 + gt という式で更新するだけです。そのコードは単純ですので省略します。(欲しい方いればgithubにでもアップします)

この先を読み進める前に・・・

レイアウトパネルの性能を見るためCanvasAbusoluteLayout を使ってますが、本来レイアウトパネルはOwnerDrawでアニメをするものではないです。
この後出てくる数字を見て 「ゲームじゃ使えねえ!」「MAUIなにこれ!?」と思わないでほしいです・・・。MAUIにはGraphicViewという描画機能があるのでGraphicViewで描写テストした記事は別途投稿します。

WPFの場合

Xamlでキャンバスを張り付けボタンなどを事前に置いていきます。
実際のコードは座標指定やイベント処理が入ります。

<Window 省略 >
    <Canvas x:Name="canvas">
        <Button Content="Start" />
        <Slider x:Name="slider" />
        <TextBlock Text="{Binding ElementName=slider,Path=Value}" />
        <TextBlock x:Name="fps" />
    </Canvas>
</Window>

ボールはスライダーで個数指定させるためにC#で描画します。単純な丸いボールです。

var ellipse = new Ellipse {
   Width = 5.0,
   Height = 5.0,
   Fill = Brushes.Black
};
canvas.Children.Add(ellipse);

ボタンを押されたら描画開始。WPFでは CompositionTarget.Renderingでフレーム毎に描画をしますので呼ばれるたびにボールの位置をアップデートし、fpsを計算します。

private void Button_Click(object sender, RoutedEventArgs e)
{
    CompositionTarget.Rendering += CompositionTarget_Rendering;
}
private void CompositionTarget_Rendering(object? sender, EventArgs e)
{
    frame++;
    foreach (var ball in _ballBist)
    {
        ball.UpdatePos(frame);
    }
    fps.Text = CalcFps();

私のPCではボール1000個ぐらいまでは60fps、2000個で約30fpsになります。
wpf.gif
mp4版

.NET MAUIの場合

MAUIには以下の4つのレイアウト(公式HPの説明)があります。
image.png

絶対座標系として AbusoluteLayout があるのでそれを使います。
位置はAbsoluteLayout.LayoutBounds添付プロパティで指定します。

<AbsoluteLayout x:Name="a">
    <Button Text="Start" AbsoluteLayout.LayoutBounds="400,5,200,33"/>
    <Slider x:Name="slider" AbsoluteLayout.LayoutBounds="400,50"/>
    <Label BindingContext="{x:Reference slider}" Text="{Binding Path=Value}" 
            AbsoluteLayout.LayoutBounds="400,80,200,25"/>
    <Label x:Name="fps" />
</AbsoluteLayout>

ボールのフレーム毎描画もWPFと同じく CompositionTarget.Rendering があったので使いました。もしかするとMAUIではもっと良い描画方法があるのかもしれません。

private void Button_Clicked(object sender, EventArgs e)
{
    Microsoft.UI.Xaml.Media.CompositionTarget.Rendering += CompositionTarget_Rendering;
}

private void CompositionTarget_Rendering(object sender, object e)
{
    frame++;
    foreach (var ball in _list)
    {
        ball.UpdatePos(frame);
    }
    fps.Text = CalcFps();
}

MAUIでの動作状況は以下の通り。100個ぐらいで30fpsでした。
mauia.gif
mp4版

残念な結果でしたのでGraphicViewで描写テストした記事を別途投稿します。

終わりに

本当はMVVMやMVU機能を書きたかったのですがなかなか時間が取れずお遊びにしました。
MAUIはXAML、データバインディング等は引き継がれているので、Xamarin経験者はほぼそのまま、WPFを作ったことがある人もそれほど違和感なく作れると思います。AndroidやiOS向けにXamarinを使ってしていた人は移行すると思います。
しかし、Windows向けGUIアプリを作りたいだけの場合、WinFormsやWPFから移行する動機が小さいと思いました。画面遷移機能などはとても便利なのですが。

描写性能についてはちゃんと本来の描画機能を使ったもので再度作ってみたいと思います。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3