作ったは良いが目的が達せられなかったのでメモしておく
チェックボックスを下記の様に並べて、ただ数字を割り振りたいだけの場合、
ViewModel側には「ReactiveCollection<ReactiveProperty<bool>> BoolList{get;}」だけ保持しておけば数字は不要です。
□1 □2 □3 □4
□5 □6 □7 □8
□9 □10 □11 □12
………
………
利点:BoolList の個数を変更すれば自動的にチェックボックスの個数・数字が増減します。
難点:Index(数字)しか出力しないので汎用性が低い。(Boolをクラスにした方が仕様変更には強いよねー)
その他:カラム数は固定ですが、Bindingを使えばViewModel側から指定できるはず。
コンバーターのソース
XAML:
ちなみに、下記みたいな縦順番にするのは無理でした…(BoolとIndex の整合性が取れなくなった)
ので、おとなしくBool ではなく オブジェクト(番号+Bool値)に変更し、Behavior を使って縦順番に変換する処理を作りました。
ここまでくるとBehaviorにする必要さえない気もしますが、列数(Column数)指定をXAMLだけに押し込めるので良いかなぁとかなんとか…
いや、列数はViewModel側に1個持って、Binding したほうが良いと思う…Behavior 作る意味なかったかなぁ…
□1 □5 □9
□2 □6 …
□3 □7 …
□4 □8 …
チェックボックスを下記の様に並べて、ただ数字を割り振りたいだけの場合、
ViewModel側には「ReactiveCollection<ReactiveProperty<bool>> BoolList{get;}」だけ保持しておけば数字は不要です。
□1 □2 □3 □4
□5 □6 □7 □8
□9 □10 □11 □12
………
………
利点:BoolList の個数を変更すれば自動的にチェックボックスの個数・数字が増減します。
難点:Index(数字)しか出力しないので汎用性が低い。(Boolをクラスにした方が仕様変更には強いよねー)
その他:カラム数は固定ですが、Bindingを使えばViewModel側から指定できるはず。
コンバーターのソース
/// <summary> /// ItemsControl で利用されるデータのIndex値を取得します。 /// </summary> public class ItemsIndexConverter : IMultiValueConverter { /// <summary> /// ItemsControl に対し、Index値を取得します /// </summary> /// <param name="values">表示元の値</param> /// <param name="targetType">データ型</param> /// <param name="parameter">画面からのパラメータ</param> /// <param name="culture">国情報(必ずen-USが来ます)</param> /// <returns>表示するデータ</returns> public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values[1] is ItemsControl itemsControl) { int value = 0; if (int.TryParse(parameter?.ToString(), out int result)) { value = result; } // アイテムのインデックスを取得 return (itemsControl.Items.IndexOf(values[0]) + value).ToString(); } return -1; // エラー時のデフォルト値 } /// <summary> /// 画面データから内部データに変換します /// </summary> /// <param name="value">表示元の値</param> /// <param name="targetTypes">データ型</param> /// <param name="parameter">画面からのパラメータ</param> /// <param name="culture">国情報(必ずen-USが来ます)</param> /// <returns>取得データ</returns> public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
XAML:
<Grid Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" Margin="10,0,5,0"> <!-- チェックボックスを均等割り付けで動的に配置 --> <ItemsControl ItemsSource="{Binding BoolList}"> <ItemsControl.ItemsPanel> <!-- Gridの中に均等割り付けで配置する --> <ItemsPanelTemplate> <!-- 必要に応じてColumns数を調整 --> <UniformGrid Columns="4" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <!-- インデックス表示用のテンプレート --> <DataTemplate> <StackPanel Orientation="Horizontal"> <!-- MultiBindingでインデックスを取得して表示 --> <CheckBox Foreground="Black" VerticalAlignment="Center" Margin="5,5,15,5" Focusable="False" IsChecked="{Binding Value}"> <CheckBox.Content> <!-- 1から始めたいのでConverterParameterに1を設定する --> <MultiBinding Converter="{StaticResource IndexConverter}" ConverterParameter="1"> <!-- アイテム自身をバインド --> <Binding /> <!-- ItemsControl全体をバインド --> <Binding RelativeSource="{RelativeSource" AncestorType="ItemsControl}"/> </MultiBinding> </CheckBox.Content> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid>
ちなみに、下記みたいな縦順番にするのは無理でした…(BoolとIndex の整合性が取れなくなった)
ので、おとなしくBool ではなく オブジェクト(番号+Bool値)に変更し、Behavior を使って縦順番に変換する処理を作りました。
ここまでくるとBehaviorにする必要さえない気もしますが、列数(Column数)指定をXAMLだけに押し込めるので良いかなぁとかなんとか…
いや、列数はViewModel側に1個持って、Binding したほうが良いと思う…Behavior 作る意味なかったかなぁ…
□1 □5 □9
□2 □6 …
□3 □7 …
□4 □8 …