Со структурой как у вас не понятно как оно должно работать.
Если сделать ItemData типизированными, то всё становится проще - wpf может по типу выбирать подходящий DataTemplate, и значения мы получаем нужного типа, а не пойми что.
public class SettingViewHost
{
public IReadOnlyCollection<SettingView>? Views { get; init; }
}
public class SettingView
{
public string? Name { get; init; }
public IReadOnlyCollection<ItemData>? Options { get; init; }
}
public class ItemData
{
public string? Name { get; init; }
public int GridRow { get; init; }
public int GridColumn { get; init; }
}
public class BooleanItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
{
public bool Value { get; set; }
}
public class StringItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
{
public string Value { get; set; } = string.Empty;
}
Собираем SettingViewHost с любым количеством SettingView с разными внутренними настройками и закидываем во вью с такими шаблонами:
<DataTemplate DataType="{x:Type local:StringItemData}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name, Mode=OneTime}" />
<TextBox Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:BooleanItemData}">
<CheckBox Content="{Binding Name, Mode=OneTime}" IsChecked="{Binding Value}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:SettingView}">
<ItemsControl ItemsSource="{Binding Options}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid IsItemsHost="True">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Grid.Column" Value="{Binding GridColumn, Mode=OneTime}" />
<Setter Property="Grid.Row" Value="{Binding GridRow, Mode=OneTime}" />
<Setter Property="Margin" Value="4" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</DataTemplate>
<DataTemplate DataType="{x:Type local:SettingViewHost}">
<StackPanel Orientation="Vertical">
<ComboBox Name="ComboBox" ItemsSource="{Binding Views}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:SettingView}">
<TextBlock Text="{Binding Name, Mode=OneTime}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ContentControl Content="{Binding ElementName=ComboBox, Path=SelectedItem}" />
</StackPanel>
</DataTemplate>
Пример сделан с Grid'ом 2х2, можно использовать любую панель. Обычный Grid для динамических целей не удобен т.к. у него фиксированное кол-во строк и столбцов. Лучше использовать UniformGrid или что-то ещё, или развлекаться с attached dependency property или MarkupExtension чтобы динамически генерировать строки и столбцы.