やりたいこと
Microsoft のチュートリアルにある「データ バインディングを使用した項目の階層の追加」を Windows App SDK で動かしたい。
まあ、このソースをいい感じに貼り付ければ動くとは思っていましたよ。プロジェクトを作成する前は。
やりかた
データテンプレートを Resources に作ることができないので、NavigationView に直接書くしかない。ちなみに、MVVM っぽくしたので、Model に NavigationView のアイテム要素を定義した。
ソリューションエクスプローラーはこんな感じ。
MainWindow.xaml
の中身
<Window <!-- 色々書いてある部分 --> xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:model="using:SampleApp.Models" mc:Ignorable="d"> <Grid> <muxc:NavigationView x:Name="navview" MenuItemsSource="{x:Bind ViewModel.Categories, Mode=OneWay}" ItemInvoked="{x:Bind ViewModel.OnItemInvoked}" Expanding="{x:Bind ViewModel.OnItemExpanding}" Collapsed="{x:Bind ViewModel.OnItemCollapsed}" PaneDisplayMode="Left"> <!-- ここに直接書き込む --> <muxc:NavigationView.MenuItemTemplate> <DataTemplate x:DataType="model:NavViewCategory"> <muxc:NavigationViewItem Content="{x:Bind Name}" MenuItemsSource="{x:Bind Children}"/> </DataTemplate> </muxc:NavigationView.MenuItemTemplate> </muxc:NavigationView> </Grid> </Window>
コードビハインドに VIewModel のプロパティを宣言しておく。
public sealed partial class MainWindow : Window { MainWindowViewModel ViewModel { get; } = new MainWindowViewModel(); public MainWindow() { this.InitializeComponent(); } }
ViewModel.cs
に関してはチュートリアルに書いてあった ObservableCollection
を実装するので省略。この記事を参考にする場合はジェネリックの型名が <NavViewCategory>
になるので注意。
NavViewCategory.cs
というモデルをつくって、そこでアイテム要素を定義しておく。
public class NavViewCategory { public String Name { get; set; } public String CategoryIcon { get; set; } public ObservableCollection<NavViewCategory> Children { get; set; } }
これで実行すると、NavigationView を動かすことができる。あとはページ遷移を実装すればいい感じになりそう。
たいへんだったこと
チュートリアルのほうは UWP 向けなので、XAML 要素が <Page>
になっているが、Windows App SDK でプロジェクトを作成すると、XAML 要素は <Window>
になっている。なので、データテンプレートを作るときからちょっと工夫しないといけなかった。
<Window.Resources> <DataTemplate x:Key="NavigationViewMenuItem" x:DataType="model:NavViewCategory"> <muxc:NavigationViewItem Content="{x:Bind Name}" MenuItemsSource="{x:Bind Children}"/> </DataTemplate> </Window.Resources>
どうやら、Windows App SDK では <Window.Resources>
が廃止になったみたい。
なので、チュートリアルにあった StaticResource
からテンプレートを読み込めなくて辛い。。。
色々調べていたら、App.xaml
に定義する方法があるみたいで、<ResourceDictionary>
の中に追記していくといいみたい。
でもこれで実行しようとしても、こんなエラーが表示されて実行できない。
the xaml binary format (xbf) generator reported syntax error '0x09c4' : property not found
結局、チュートリアルにあった StaticResource
は使えそうにないので他の方法を探すしかなかった。
何もわからないまま、しばらくぼーっとしていると StaticResource
は MenuItemTemplate
に対して読み込んでいたのをきっかけに、「もしかしたら <MenuItemTemplate>
みたいな要素があるのでは?」とひらめいた。そして、データテンプレートを <muxc:NavigationView.MenuItemTemplate>
で挟めばいいことに気づき、上記のような手法を用いたところ実行できるようになった。
Windows App SDK (WinUI3) に関する記事が少なくて、GitHub Issue を見たりしていたけどこのようなケースが見当たらなかった。結局これだけのために半日くらい消費した挙げ句、疲れてしまった。。。