Search code examples
c#xaml.net-6.0maui

How do I initialize a table with data, which is stored in a list in a MAUI app?


In my app I have a few pages and in one of them I want to initialize a table that holds some data.

My problem is that I do not know how many rows there are going to be. The header should be static from the beginning and after the header I want a table that holds the information for the respective columns.

At the moment the XAML file looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.PZEAnwenderkorrekturen"
             Title="PZE Anwenderkorrekturen">
    <StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand" Padding="5,5,5,5">
        <Label Text="Kommen/Gehen" FontSize="40" HorizontalOptions="CenterAndExpand" FontFamily="Bold" />
        <StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand" Spacing="10">
            <Button Text="KOMMEN" 
                    TextColor="Black"
                    FontAttributes="Bold"
                    FontSize="Large"
                    WidthRequest="250" 
                    HeightRequest="150"
                    BackgroundColor="DarkSeaGreen" 
                    Clicked="Button_Clicked" 
                    BorderColor="Black" 
                    BorderWidth="2"
                    CornerRadius="50"
                    Margin="10"/>
            <Button Text="GEHEN"
                    TextColor="Black"
                    FontAttributes="Bold"
                    FontSize="Large"
                    WidthRequest="250" 
                    HeightRequest="150" 
                    BackgroundColor="OrangeRed" 
                    Clicked="Button_Clicked_1" 
                    BorderColor="Black" 
                    BorderWidth="2"
                    CornerRadius="50"
                    Margin="10"/>
        </StackLayout>
            
        <!-- The table should be here -->
        <StackLayout BackgroundColor="LightGray">
        </StackLayout>
    
        <StackLayout BackgroundColor="LightGray">
            <Label Text="Hier ist der dritte Bereich"></Label>
        </StackLayout>

        <StackLayout BackgroundColor="LightGray">
            <Label Text="Hier ist der vierte Bereich"></Label>
        </StackLayout>

    </StackLayout>
</ContentPage>

So I created a new Buchung class like this:

public class Buchung
{
    public string Tag { get; set; }
    public DateTime Datum { get; set; }
    public string Von { get; set; }
    public string Bis { get; set; }
    public string Fehlgrund { get; set; }
    public string Anw { get; set; }
    public string Soll { get; set; }
    public string GLZ { get; set; }
    public string Gesamt { get; set; }
}

And after I had the Buchung class, I started to create instances of it in a ViewModel like this:

public class BuchungenViewModel
{
    public ObservableCollection<Buchung> Buchungs { get; set; } = new ObservableCollection<Buchung>
    {
        new Buchung
        {
            Tag = "Montag",
            Datum = DateTime.Today,
            Von = "07:00",
            Bis ="17:00",
            Anw = "10:00",
            Soll = "08:00",
            GLZ = "02:00",
            Gesamt = "10:00"
        },
        new Buchung
        {
            Tag = "Dienstag",
            Datum = DateTime.Today.AddDays(1),
            Von = "09:00",
            Bis ="17:00",
            Anw = "08:00",
            Soll = "08:00",
            GLZ = "00:00",
            Gesamt = "08:00"
        },
        new Buchung
        {
            Tag = "Mittwoch",
            Datum = DateTime.Today.AddDays(2),
            Von = "07:00",
            Bis ="12:00",
            Anw = "05:00",
            Soll = "08:00",
            GLZ = "-03:00",
            Gesamt = "05:00"
        }
    };
}

The table header should look something like this:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
        
    <Grid.RowDefinitions>
        <RowDefinition Height="50"></RowDefinition>
    </Grid.RowDefinitions>
    
    <Label Grid.Row="0" Grid.Column="0" Text="Tag" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="1" Text="Datum" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="2" Text="Fehlzeiten" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="3" Text="Von" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="4" Text="Bis" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="5" Text="Anw" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="6" Text="Soll" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="7" Text="GLZ" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
    <Label Grid.Row="0" Grid.Column="8" Text="Gesamt" TextColor="Beige" BackgroundColor="{StaticResource Tertiary}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Header" FontAttributes="Bold" Margin="2,2,2,2"></Label>
</Grid>

Jason mentioned something with a BindableLayout, so I tried this:

<StackLayout BindableLayout.ItemsSource="{Binding Buchungs}" Orientation="Horizontal">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Label Text="{Binding .}" TextColor="Black" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Body" FontAttributes="None" Margin="2,2,2,2"></Label>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

But it is still not working. If someone could help me with that, I would re6aly appriciate it.


Solution

  • Using a BindableLayout is a good approach here, as Jason recommended.

    You need to make sure that you bind the data correctly. Instead of passing . to the binding, which means the entire object, you need to bind to a specific property of the object, e.g. Tag, because the Label's Text property expects a string, not Buchung:

    <StackLayout BindableLayout.ItemsSource="{Binding Buchungs}" Orientation="Horizontal">
        <BindableLayout.ItemTemplate>
            <DataTemplate x:DataType="model:Buchung">
                <Label Text="{Binding Tag}" TextColor="Black" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="Body" FontAttributes="None" Margin="2,2,2,2"></Label>
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </StackLayout>
    

    Note that you might want to change the Orientation of the StackLayout to Vertical or directly use the VerticalStackLayout and place a HorizontalStackLayout or a Grid inside the DataTemplate to position the different properties of your data horizontally.

    This is just to display the data. You'll still need to add the layout for the table header.