やりたいこと
複数項目を扱うコレクション/リストを扱うコントールでは、幅に応じて自動で折り返してくれる。その折返しを制御したい。
具体的には、必ず偶数列で折り返したい。
例:2列の次は4列になって欲しい:
対象/環境
- UWP
- コントロール:GridView, ListView, ItemsRepeater 等
- Visual Studo 2019
1. Behaviorを使って SizeChangedを監視+GridView
下記サイトを参照 UWP の GridView でいい感じにコンテンツを配置したい@みかづきメモ https://mikazuki.hatenablog.jp/entry/2016/06/26/224545
ほぼ、上記サイトの通りです。
「偶数で折返し」箇所の為に、1行だけ修正した。
private void OnSizeChanged(object sender, SizeChangedEventArgs e) { var size = e.NewSize; var assumSize = AssumSize.GetAssumSize(this.AssociatedObject); var maxColumn = Math.Floor(size.Width / assumSize); // ↓ここだけ変更(他一緒)。最大列数を偶数に寄せてる。(3列なら2列、15列なら14列にしてしまう) maxColumn = (maxColumn % 2 == 0) ? maxColumn : maxColumn - 1; var adjustedSize = assumSize + size.Width % assumSize / maxColumn; this.AssociatedObject.ItemHeight = adjustedSize; this.AssociatedObject.ItemWidth = adjustedSize; }
2020/07/21:追記 これ追加すれば列数指定できるのか・・・。
this.AssociatedObject.MaximumRowsOrColumns = (int)maxColumn;
2. ItemsRepeater(WinUI2.x)で、SizeChangedを監視。ItemsRepeater.LayoutのMaximumRowsOrColumns値を制御
気持ち的には これが一番スッキリした。
- SizeChanged時に処理開始
- サイズによって、MaximumRowsOrColumnsを偶数に寄せる
1と似てるが、設定するのが「列数」なのがいい。「偶数にしたい!」という意図に近い。
<muxc:ItemsRepeater x:Name="repeater2" ItemsSource="{x:Bind Path=Vm.MySource}" SizeChanged="repeater2_SizeChanged"> <muxc:ItemsRepeater.Layout> <muxc:UniformGridLayout x:Name="unilayout" MinItemWidth="150"/> </muxc:ItemsRepeater.Layout> </muxc:ItemsRepeater> private void repeater2_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e) { var iRepeater = sender as ItemsRepeater; if(iRepeater == null) { return; } // 列幅は150固定とする。2列(300)入る個数を計算し2倍する。偶数のみになるハズ。 var col = (int)(iRepeater.ActualWidth / 300) * 2; this.unilayout.MaximumRowsOrColumns = col; }
・・・が、 ItemsRepeater はDragDropに(まだ)未対応だった。
ItemsRepeater を GridView にしたらうまく動かなくなった。(あきらめた)
MaximumRowsOrColumns は ItemsRepeater以外でもでも使える・・・ハズ。
なので、2のGridView版はリトライしたい。
> 2020/07/21:追記 できた・・・。
3. ItemsRepeater(WinUI2.x)で、ItemsRepeater.Layout 部分を自作。
やっていることは1と同じ。
こんな感じのことができるらしいので、踏襲しようとした。
<ScrollViewer x:Name="scrollViewer"> <muxc:ItemsRepeater ItemsSource="{x:Bind NumberedItems}" Layout="{StaticResource MyFeedLayout}" ItemTemplate="{StaticResource SimpleItemTemplate}" /> <ScrollViewer/>
↑ こんな感じで、Layoutを指定する。Layoutは下記。(ItemTemplate とは異なる)
<common:ActivityFeedLayout x:Key="MyFeedLayout" ColumnSpacing="12" RowSpacing="12" MinItemSize="80, 108"/>
↑ common:ActivityFeedLayout というのが自作クラス。
↓ ActivityFeedLayout のソース
MeasureOverrideとか、.Netっぽい。この辺を修正して偶数列になるようアイテムの「幅」を調整する。
desiredItemWidth(アイテムの幅) を調整する。奇数になりそうだったら幅を大きくして奇数になるのを回避、偶数になりそうだったら幅を小さくして表示。(という小細工)
ソース省略。
できた・・・けど、自分で書いた内容を忘れそう・・・。(ので採用見送り)
補足
- 列幅/列数 制御すること自体を見直した方がいいかも?
- 今は「1」の方法だけど、やっぱり「2をGridView」でやってみたい。
2020/07/21:追記 「2をGridView」 できました。簡単でした・・・。
以上