I develop my App UI with XAML and in Background I run a C# program.
To make it bit easier to explain: Lets say the program shall Display Paramters in a ListView/Grid.
The Parameter Value can be a single value (displayed as Label) or a vector/matrix (displayed as Grid inside this cell). I have no idea how I can also add a other grid here with unknown column number, the number will be different for each paramter.
All the Parameters are in a List and loaded with a ItemSource + DisplayMemberBinding dynamically.
So what I Need: - A Grid in a DataTemplate - A Grid with unknown number of rows
<DataTemplate x:Key="labelTemplate">
<Label Content="{Binding Path=Value}" Width="Auto"></Label>
</DataTemplate>
<DataTemplate x:Key="table2DTemplate">
</DataTemplate>
<local:ParameterTemplateSelector
x:Key="parameterTemplateSelector"
LabelTemplate="{StaticResource labelTemplate}"
Table2DTemplate ="{StaticResource table2DTemplate}"/>
MY Datatempaltes + TemplateSelector:
<ListView ItemsSource="{Binding Parameters}" Margin="10,156,10.286,10.429" x:Name="listBox1" FontSize="8" Background="White" Foreground="Black" BorderBrush="#FF60EFBB">
<ListView.View>
<GridView>
<GridViewColumn
Header="Name"
Width="Auto"
DisplayMemberBinding="{Binding Name}" />
<GridViewColumn
Header="Value"
Width="Auto"
CellTemplateSelector="{StaticResource parameterTemplateSelector}" />
<GridViewColumn
Header="Unit"
Width="Auto"
</GridView>
</ListView.View>
</ListView>
Here's what you want to do. The value converter is necessary because you can't bind an ItemsControl (or any of its subclasses like ListBox, ListView, etc.) to a two-dimensional array. So we convert the 2D array into a List<List<String>>
and display that in nested ItemsControls. The converter is included below.
This could be simplified if you're willing to use List<List<String>>
throughout your code as a substitute for string[,]
, but that may not be practical.
<DataTemplate x:Key="table2DTemplate">
<ItemsControl
ItemsSource="{Binding Value, Converter={StaticResource ListOfListsFrom2DArray}}"
>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Rows="1"
/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
Converter. There's not much here but a LINQ expression I stole from another StackOverflow answer.
public class ListOfListsFrom2DArray : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var values = value as string[,];
// https://stackoverflow.com/a/37458182/424129
var result = values.Cast<string>()
// Use overloaded 'Select' and calculate row index.
.Select((x, i) => new { x, index = i / values.GetLength(1) })
// Group on Row index
.GroupBy(x => x.index)
// Create List for each group.
.Select(x => x.Select(s => s.x).ToList())
.ToList();
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}