Search code examples
xamllistviewuwpdynamic-columns

UWP (xaml) - load dynamic columns and rows to GridView


I'm trying to load dynamic data with rows and columns to a GridView or ListView control so it looks like a table with headers and rows. My aim is to do something like this:

ListView table layout

I've found that layout explanation on this site : ListView but the problem is I've tried it out for dynamic columns but nothing worked...

My code so far looks like this:

<ListView ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" 
              Name="GridViewList" Margin="0,20,0,0" HorizontalAlignment="Stretch" IsHitTestVisible="False" SelectedIndex="-1">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="localVM:GridViewRow">
                <Grid>
                    <ItemsControl ItemsSource="{x:Bind Columns}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate x:DataType="localVM:GridViewColumn">
                                <Grid x:Name="ColumnsViewGrid">
                                    <TextBlock Grid.Row="0" Text="{x:Bind Title}" TextWrapping="WrapWholeWords" FontWeight="Bold" TextTrimming="CharacterEllipsis"
                                               Visibility="{Binding IsHeader, Converter={StaticResource BoolToVisibilityConverter}}"/>
                                    <TextBlock Grid.Row="1" Text="{x:Bind Value}" TextWrapping="WrapWholeWords" TextTrimming="CharacterEllipsis"/>
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

Columns are populated dynamically and everytime they have a different count.

Columns are stored in GridViewRow class:

public int RowIndex { get; private set; }

    public List<GridViewColumn> Columns { get; }

    /// <summary>
    /// Initialized a new instance of <see cref="GridViewRow"/> class
    /// </summary>
    /// <param name="rowIndex">Row index</param>
    /// <param name="isHeader">If row is header it's true</param>
    /// <param name="columns">Columns </param>
    /// <param name="headers">Table headers </param>
    public GridViewRow(int rowIndex, List<GridViewColumn> columns)
    {
        this.RowIndex = rowIndex;

        this.Columns = columns;
    }

And GridViewColumn class looks like this:

public string Value { get; private set; }

    public string Title { get; private set; }

    public bool IsHeader { get; private set; }

    public GridViewColumn(string title, string value, bool isHeader)
    {
        this.Title = title;
        this.Value = value;
        this.IsHeader = IsHeader;
    }

Many thanks for your help!


Solution

  • All,

    I managed to solve the issue with below example:

    <ListView Grid.Row="2" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" ItemContainerStyle="{StaticResource ListViewItemStyle}"
                  Name="ListViewTemp" Margin="0,20,0,0" HorizontalAlignment="Stretch" IsHitTestVisible="False" BorderBrush="DimGray" BorderThickness="0,0,0,1">>
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="localVM:Row">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <ItemsControl Grid.Row="0" ItemsSource="{x:Bind Columns}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate x:DataType="localVM:Column">
                                    <ScrollViewer>
                                        <Grid Padding="10" Background="{x:Bind IsHeader, Converter={StaticResource BoolToBackgroundConverter}}"
                                                BorderBrush="DimGray" BorderThickness="0,0,1,0">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="{x:Bind Size}"/>
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Text="{x:Bind Title}" TextWrapping="WrapWholeWords" FontWeight="Bold" TextTrimming="CharacterEllipsis"
                                                   Visibility="{Binding IsHeader, Converter={StaticResource BoolToVisibilityConverter}}" Foreground="White"/>
                                            <TextBlock Text="{x:Bind Value}" TextWrapping="WrapWholeWords" TextTrimming="CharacterEllipsis"/>
                                        </Grid>
                                    </ScrollViewer>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                        </ItemsControl>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    

    And I'm calculating a Size of a column like this:

    double listViewWidth = ListViewTemp.ActualWidth;
    
            double columnWidth = listViewWidth / (rows[0].Columns.Count);
    
            foreach (var row in rows)
            {
                foreach (var column in row.Columns)
                {
                    column.Size = new GridLength(columnWidth);
                }
            }
    

    Thanks for all your help!