要素の選択機能とかいらない、もっとシンプルに要素を列挙したいんです!っていうときに 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=0x409 namespace CompactSampleApp { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public IEnumerable<string> Items { get; } public MainPage() { this.InitializeComponent(); Items = Enumerable.Range(1, 10000).Select(x => $"Item {x}").ToArray(); } } }
<Page x: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"> <Grid x:Name="grid" Grid.Row="1" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <controls:ItemsRepeater ItemsSource="{x:Bind Items}" /> </Grid> </Page>
こんな感じ。
ScrollViewer にも入れることが出来ます。
<Page x: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"> <Grid x: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 でデータの見た目も変えれる。
<Page x: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"> <Grid x: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" /> <TextBlock Grid.Column="1" Style="{StaticResource BodyTextBlockStyle}" Text="{x:Bind}" Margin="10,0"/> <TextBlock Grid.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 みたいなのがさくっと作れていい感じ。
<Page x: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"> <Grid x: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" /> <TextBlock Grid.Column="1" Style="{StaticResource BodyTextBlockStyle}" Text="{x:Bind}" Margin="10,0"/> <TextBlock Grid.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 とかではマッチしないときは、これを使うことになりそう。