ここで懸念を分離したいと思います。
モデルは次のような構造になります。
public class GroupBoxCollection
{
public List<GroupBoxContent> Collections { get; set; }
}
public class GroupBoxContent
{
public string GroupBoxName { get; set; }
public List<GroupBoxItem> Items { get; set; }
}
public class GroupBoxItem
{
public string ItemName { get; set; }
public bool IsChecked { get; set; }
}
XAML は次のようになります。SL4 にはデフォルトで GroupBox がないため、ここでは GroupBox を使用していません。代わりに Grid を使用しますが、コードを変更して自分で使用することもできます :)
<ListBox x:Name="TestListBox" ItemsSource="{Binding Collections}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5" Background="Azure">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding GroupBoxName}" />
<ListBox Grid.Row="1" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding ItemName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
コード ビハインドでは、次のようなことができます。
TestListBox.DataContext = [an instance of GroupBoxCollection here];
もちろん、必要に応じてスタイルを設定/テンプレート化したり、ListBox 以外のものを使用したりすることで、これをきれいにすることができますが、それが全体的な考え方です。
ノート:
必要に応じて、モデルに INotifyPropertyChanged を実装したり、List の代わりに ObservableCollection を使用したりする必要がある場合もあります。ユーザーがチェックボックスのいずれかをチェック/チェック解除したときにビューでモデルを変更する場合は、TwoWay データバインディングを使用する必要がある場合もあります。
私のサンプルをそのままテストして何が起こるかを確認したい場合は、DataContext として設定する前に、GroupBoxCollection (TestListBox の DataContext として設定したもの) のインスタンスを設定してください。