要素の選択機能とかいらない、もっとシンプルに要素を列挙したいんです!っていうときに ItemsControl 使いますが、こいつは仮想化サポートしてないです。
WinUI に追加された ItemsRepeater は、仮想化がイケる ItemsControl みたいなやつです。
使ってみよう
使い方は ItemsSource に適当なコレクションをバインドする感じです。
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409namespace CompactSampleApp { /// <summary>/// An empty page that can be used on its own or navigated to within a Frame./// </summary>publicsealedpartialclass MainPage : Page { public IEnumerable<string> Items { get; } public MainPage() { this.InitializeComponent(); Items = Enumerable.Range(1, 10000).Select(x => $"Item {x}").ToArray(); } } }
<Pagex:Class="CompactSampleApp.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:Microsoft.UI.Xaml.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:CompactSampleApp"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"mc:Ignorable="d"><Gridx:Name="grid"Grid.Row="1"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><controls:ItemsRepeater ItemsSource="{x:Bind Items}" /></Grid></Page>
こんな感じ。
ScrollViewer にも入れることが出来ます。
<Pagex:Class="CompactSampleApp.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:Microsoft.UI.Xaml.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:CompactSampleApp"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"mc:Ignorable="d"><Gridx:Name="grid"Grid.Row="1"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><ScrollViewer><controls:ItemsRepeater ItemsSource="{x:Bind Items}" /></ScrollViewer></Grid></Page>
Windows 10 1809 より前で動かすことがあるケース(というか今時点では、ほとんどそのケースなのかな?)では ItemsRepeaterScrollHost
で ScrollViewer
をラップしないといけないみたいです。
<controls:ItemsRepeaterScrollHost><ScrollViewer><controls:ItemsRepeater ItemsSource="{x:Bind Items}" /></ScrollViewer></controls:ItemsRepeaterScrollHost>
ItemTemplate や ItemTemplateSelector でデータの見た目も変えれる。
<Pagex:Class="CompactSampleApp.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:Microsoft.UI.Xaml.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:CompactSampleApp"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:system="using:System"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"mc:Ignorable="d"><Gridx:Name="grid"Grid.Row="1"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><controls:ItemsRepeaterScrollHost><ScrollViewer><controls:ItemsRepeater ItemsSource="{x:Bind Items}"><controls:ItemsRepeater.ItemTemplate><DataTemplate x:DataType="system:String"><Grid Margin="10"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /><ColumnDefinition Width="Auto" /></Grid.ColumnDefinitions><SymbolIcon Symbol="Accept" /><TextBlockGrid.Column="1"Style="{StaticResource BodyTextBlockStyle}"Text="{x:Bind}"Margin="10,0"/><TextBlockGrid.Column="2"Style="{StaticResource BodyTextBlockStyle}"Text="{x:Bind system:String.Format('{0}文字', Length)}"Margin="10,0"/></Grid></DataTemplate></controls:ItemsRepeater.ItemTemplate></controls:ItemsRepeater></ScrollViewer></controls:ItemsRepeaterScrollHost></Grid></Page>
レイアウトは StackLayout と UniformGridLayout が提供されていて、デフォルトが縦方向指定の StackLayout。 StackLayout は、縦並び横並びであんまりおもしろくないけど UniformGridLayout は WPF でいうところの WrapPanel みたいなのがさくっと作れていい感じ。
<Pagex:Class="CompactSampleApp.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:Microsoft.UI.Xaml.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:CompactSampleApp"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:system="using:System"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"mc:Ignorable="d"><Gridx:Name="grid"Grid.Row="1"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><controls:ItemsRepeaterScrollHost><ScrollViewer><controls:ItemsRepeater ItemsSource="{x:Bind Items}"><controls:ItemsRepeater.Layout><controls:UniformGridLayout MinItemWidth="200"MinColumnSpacing="10"ItemsJustification="Center"Orientation="Horizontal" /></controls:ItemsRepeater.Layout><controls:ItemsRepeater.ItemTemplate><DataTemplate x:DataType="system:String"><Grid Margin="10"Background="LightBlue"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition /><ColumnDefinition Width="Auto" /></Grid.ColumnDefinitions><SymbolIcon Symbol="Accept" /><TextBlockGrid.Column="1"Style="{StaticResource BodyTextBlockStyle}"Text="{x:Bind}"Margin="10,0"/><TextBlockGrid.Column="2"Style="{StaticResource BodyTextBlockStyle}"Text="{x:Bind system:String.Format('{0}文字', Length)}"Margin="10,0"/></Grid></DataTemplate></controls:ItemsRepeater.ItemTemplate></controls:ItemsRepeater></ScrollViewer></controls:ItemsRepeaterScrollHost></Grid></Page>
そのほかに
要素に対するライフサイクルイベントや、グルーピングは直接サポートされてないけどグルーピングの UI を作る方法とかがドキュメントにたくさん書いてあります。
まとめ
ちょっと本格的なコレクション UI 作るときや、ListView とかではマッチしないときは、これを使うことになりそう。