.NET6 preview4
2021/05/25に.NET6 preview4が出ましたね!
それと同時にMAUI preview4が出ました。
さっそくサンプルのWeatherTwentyOneを見つつ、全体の作りと、preview3であれ?と思ったところを見てみます。
プラットフォーム毎の起動パターン
基本的にはXamarinの起動パターンを踏襲しています。
iOS / MacCatalyst
Main
からUIApplication.Main
を使ってUIKitのアプリケーションを起動します。
そして[Register("")]
されている名前のDelegateを呼び出します。
…この辺、まんまXamarinですね。
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate<Startup>
{
}
呼び出されるDelegateはMauiUIApplicationDelegate<>
を継承したクラスで、設定されているテンプレートのクラスをスタートアップにして呼び出しているようです。
Android
[Activity(MainLauncher = true)]
でデフォルトActivityを指定。
[Application]
でアプリケーションクラスを指定します。
やっぱりXamarinです。
[Activity(MainLauncher = true)]
public class MainActivity : MauiAppCompatActivity
{
}
[Application]
public class MainApplication : MauiApplication<Startup>
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
{
}
}
[Application]
のクラスはMauiApplication<>
を継承したクラスで、設定されているテンプレートのクラスをスタートアップにして呼び出しているようです。
WinUI
WinUIの場合、少しジレンマがあるようです。
起動に使用するApp.xaml
とApp.xaml.cs
は共通部分に使いたいです。
しかも、XAMLでプリケーションを指定したいのだがスタートアップクラスをテンプレートとして指定したい。
ということで、MiddleApp
みたいなのをいったん作った後、XAMLで指定するようです。
(サンプルでも「イケてないね」みたいなコメント書いてあります…)
<local:MiddleApp
x:Class="WeatherTwentyOne.WinUI.WindowsApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WeatherTwentyOne.WinUI">
</local:MiddleApp>
public partial class WindowsApp : MiddleApp
{
}
public class MiddleApp : MauiWinUIApplication<Startup>
{
}
アプリケーションのクラスはMauiWinUIApplication<>
を継承したクラスで、設定されているテンプレートのクラスをスタートアップにして呼び出しているようです。
Startup
各プラットフォームで指定したStartupクラスは、起動時の共通設定を行うようになっています。
ASP.NetCoreのような感じですね。
public class Startup : IStartup
{
public void Configure(IAppHostBuilder appBuilder)
{
appBuilder
.UseCompatibility()
.UseMauiApp<App>()
.ConfigureServices(services =>
{
# if WINDOWS
services.AddSingleton<ITrayService, WinUI.Windows.TrayService>();
services.AddSingleton<INotificationService, WinUI.Windows.NotificationService>();
# elif MACCATALYST
services.AddSingleton<ITrayService, MacCatalyst.TrayService>();
services.AddSingleton<INotificationService, MacCatalyst.NotificationService>();
# endif
})
.ConfigureFonts((fonts)=>
{
fonts.AddFont("fa-solid-900.ttf", "FontAwesome");
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-SemiBold.ttf", "OpenSansSemiBold");
});
}
}
サービス登録などもここで行います。
(UnityやDrylocのようなDIものではなく、Xamarinのプラットフォーム毎のサービス)
この後、この中のUseMauiApp<>
で指定したMAUI本来のアプリケーションを起動させるようです。
App.xaml, App.xaml.cs
MAUIのアプリケーション起動内では、ウインドウを作ります。
public partial class App : Microsoft.Maui.Controls.Application
{
protected override IWindow CreateWindow(IActivationState activationState)
{
Microsoft.Maui.Controls.Compatibility.Forms.Init(activationState);
return new Microsoft.Maui.Controls.Window(
new NavigationPage(
new HomePage()
)
);
}
}
//(Windowを作るところだけを抜粋)
Windowは、Windowクラスを使って作ればよいです。
そして、コンストラクタ引数でPage
クラスを指定します。
preview3では…(余談)
preview3のIWindow
では、IView
を保持して、継承したビューを表示するようになっていました。
なので、
public class MainPage : ContentPage
{
public IView View => Content;
}
public class Window : IWindow
{
public IPage Page { get; }
public IView View => Page.View;
}
のような実装になっていたので、「あれ?Pageはどこいった?あれNSViewControllerに変換できただろう?」と思ったものです。
(基本macOSでやってたもので…)
というのも、MauiUIApplicationDelegate
の実装で、
Window = new UIWindow
{
RootViewController = window.View.ToUIViewController(mauiContext)
};
という、ViewをUIViewController
に変換している部分があったため…。
preview4のWindowの実装(Window.Impl.cs)で、下記のような指定になっているので、ああ、ちゃんとPageが指定できるようになっているんだな、とは思いましたが。
public Page? Page
{
get => _page;
set
{
if (_page != null)
InternalChildren.Remove(_page);
_page = value;
if (_page != null)
InternalChildren.Add(_page);
if (value is NavigableElement ne)
ne.NavigationProxy.Inner = NavigationProxy;
}
}
IView IWindow.View
{
get => Page ?? throw new InvalidOperationException("No page was set on the window.");
set => Page = (Page)value;
}
最後に
というわけで、無事画面周りの実装も
Window
Page
View
と、階層構造になっていることが確認でき、一安心したpreview4でした。
じっさいの作成では、MAUIのテンプレートから作って必要なプラットフォームのみ作成、ページの作成にはXamarinで使っていたPageやViewを使えばいい、ということになりそうです。
ということで、テンプレートとして出力されるソースをいじるのは、App.xaml.csあたりからで良さげ。