Uno Platformというものがある
UWPのコードをベースにして、自力でXAMLを解釈して、Xamarinの上でViewをいい感じに動かすっていうアプローチ。Xamarin.Formsのラッパーではない。
俺たちが期待してるUniversalはこれなんだよ、いいからMSは早く買収するんだ。という気持ちを抑えながら、公式ページで図解されている構造を見てみるとこういう感じ。
あれこれなんか4年前に似たような図を描いたような気がする*1…
簡単なコードなら普通に動くし、複雑なコードもUno Platformをターゲットに最初から作ればわりかしちゃんと動く。よくできている。
実際にWindows 10の電卓が移植されていて、Play StoreとかApp Storeからダウンロードできるので、とりあえず「すげーーー」って言うには電卓を入れるのがおすすめ。
apps.apple.com play.google.comただ、本物のUWPと、UWPに似せたAPIを提供したXamarinだとどうしても違うことがあるので現行のUWPのコードを突っ込めばそのまま動くか?と聞かれれば答えは”ほぼNo”という感じ。 実際にコピペしたら全然動かんかった。
implicit styleが動かんという話
さて、いろいろ動かないことはあるんだけども一番困ったimplicit styleが動かんというトピックを紹介しておきます。 アプリの見た目をそろえるときにこういう書き方をすることがあります。
<Application x:Class="UnoApp2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Application.Resources> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Red" /> </Style> </Application.Resources> </Application>
すべてのTextBlock
の文字色が赤になることを期待しています。当然UWPで実行すると赤で表示されます。
ところが、Uno Platformでビルドすると次のメッセージが得られます。
Error reading response 1>MSBUILD : error : Generation failed: System.AggregateException: 1 つ以上のエラーが発生しました。 ---> System.InvalidOperationException: Generation failed for Uno.UI.SourceGenerators.XamlGenerator.XamlCodeGenerator. System.AggregateException: 1 つ以上のエラーが発生しました。 ---> System.Exception: Processing failed for file ***\UnoApp2.Shared\App.xaml ---> System.Exception: Implicit styles in inline resources are not supported (Application, Line 1:2) 1>MSBUILD : error : 場所 Uno.UI.SourceGenerators.XamlGenerator.XamlFileGenerator.RegisterResources(XamlObjectDefinition topLevelControl) 1>MSBUILD : error : 場所 Uno.UI.SourceGenerators.XamlGenerator.XamlFileGenerator.BuildApplicationInitializerBody(IndentedStringBuilder writer, XamlObjectDefinition topLevelControl) 1>MSBUILD : error : 場所 Uno.UI.SourceGenerators.XamlGenerator.XamlFileGenerator.InnerGenerateFile() 1>MSBUILD : error : 場所 Uno.UI.SourceGenerators.XamlGenerator.XamlFileGenerator.GenerateFile()
なんやかんや書いてますが、要するにx:Key
が指定されていない暗黙的なリソースはサポートされてないですよ。ということらしいのです。めっちゃ困る。
これに関連したIssue(というかPR)をGitHubで探すとこれが見つかります。
ここの、 What is current behavior? に書いてあるのですが
Uno only supports global-level resources, including implicit styles
らしいのです。このglobal-levelがポイントです。
解決する話
先のPRから現状の実装ではglobal-levelならimplicit stylesが動く。と読み取れます。 じゃぁglobal-levelなstyleとはなんぞや。という話があり、ドキュメントなどから雰囲気をつかむと要するにこれです。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Red" /> </Style> </ResourceDictionary>
てきとうにXAMLを作って、ResourceDictionary
を書いて、その中ならimplicit styleと呼ばれているものを書きまくってもいいということらしいのです。実際動かすと動きます。
そんじゃこれ、UWPで動くんかというと動きません。実行結果はこれです。
ではこれが、全部の環境で期待値となるXAMLはどうなるか。というと、App.xamlでResourceDictionaryとして読めばいい。
<!-- Themes/ImplicitStyles.xaml --> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Red" /> </Style> </ResourceDictionary> <!-- App.xaml --> <Application x:Class="UnoApp2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Application.Resources> <ResourceDictionary Source="Themes/ImplicitStyles.xaml" /> </Application.Resources> </Application>
これで最初の画像と同じ結果が得られます(見た目変らないので画像省略)。
だんだん奇妙なXAMLになってきましたね。さすがはCross Platform…たまんないですね…