Search code examples
c#.netxamlmaui

CollectionView only shows items, when I have a private or no setter in .NET MAUI


Everthing worked perfectly fine and all Items appear like they should: Android Emulator, all working

But when I add the setter of a list item in the object class from this:

using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shopping_List.Models
{
    public class Liste
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }

        public string Name { get; set; }

        public List<string> ItemListe { get; } = new List<string>();
    }
}

To this (Added setter by the ItemListe):

using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shopping_List.Models
{
    public class Liste
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }

        public string Name { get; set; }

        public List<string> ItemListe { get; set; } = new List<string>();
    }
}

the next time I start the emulator then, no lists appeared anymore. Here are the other classes of my project that are important for this problem: Service class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SQLite;
using Shopping_List.Models;
using System.Xml.Linq;

namespace Shopping_List.Services
{
    public static class ListService
    {
        static SQLiteAsyncConnection db;
        
        static async Task Init()
        {
            if (db != null)
                return;
            
            //Get an absolute path to the database file
            var databasePath = Path.Combine(FileSystem.AppDataDirectory, "MyData.db");
            db = new SQLiteAsyncConnection(databasePath);

            await db.CreateTableAsync<Liste>();
        }

        public static async Task AddList(string name)
        {
            await Init();
            var liste = new Liste
            {
                Name = name
            };

            await db.InsertAsync(liste);
        }

        public static async Task RemoveList(int id)
        {
            await Init();
            await db.DeleteAsync<Liste>(id);
        }

        public static async Task<IEnumerable<Liste>> GetList()
        {
            await Init();

            var liste = await db.Table<Liste>().ToListAsync();
            return liste;
        }
    }
}

ViewModel Class:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shopping_List.Models;
using Shopping_List.Services;
using Shopping_List.View;

namespace Shopping_List.ViewModel
{
    public partial class MainViewModel : ObservableObject
    {
        [ObservableProperty]
        ObservableCollection<Liste> liste;

        public MainViewModel()
        {
            
            Liste = new ObservableCollection<Liste>();
            Refresh();

            //Nachricht von der ListCreatorPage erhalten
            WeakReferenceMessenger.Default.Register<DataMessage>(this, (r, message) =>
            {
                // Handle the received message
                string text = message.Value;
                
                Add(text);
            });
        }
        //Hinzufügen einer Liste zur Database
        [RelayCommand]
        async Task Add(string name)
        {
            
            await ListService.AddList(name);
            await Refresh();
        }
        //Entfernen einer Liste aus der Database
        [RelayCommand]
        async Task Remove(Liste liste)
        {
            await ListService.RemoveList(liste.Id);
            await Refresh();
        }
        //Aktualisieren der Listen auf der MainPage
        [RelayCommand]
        async Task Refresh()
        {
            Liste.Clear();
            var liste = await ListService.GetList();
            foreach (var l in liste)
            {
                Liste.Add(l);
            }
        }

        //Navigation zur 
        [RelayCommand]
        async Task GoToActualListAsync(Liste liste)
        {
            if(liste is null)
                return;

            await Shell.Current.GoToAsync($"{nameof(ActualListPage)}", true,
                new Dictionary<string, object>
                {
                    {"Liste", liste}
                });
        }
        
        
        //Navigation zur ListCreatorPage
        [RelayCommand]
        async Task GoToListCreatorAsync()
        {
            await Shell.Current.GoToAsync(nameof(ListCreatorPage));
        }

        
        
    }
}

XAML View Page:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Shopping_List.MainPage"
             xmlns:viewmodel="clr-namespace:Shopping_List.ViewModel"
             x:DataType="viewmodel:MainViewModel"
             xmlns:model="clr-namespace:Shopping_List.Models"
             Title="Meine Listen"
             >
    <Grid
    ColumnDefinitions="*, *"
    ColumnSpacing="5"
    RowDefinitions="*,Auto"
    RowSpacing="0"
    >
        <CollectionView Grid.Row="0" Grid.ColumnSpan="2"
                        ItemsSource="{Binding Liste}"
                        SelectionMode="None">
            
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="model:Liste">
                    <SwipeView>
                        <SwipeView.RightItems>
                            <SwipeItems>
                                <SwipeItemView >
                                    <Frame BackgroundColor="Red"
                                           WidthRequest="100">
                                        <Frame.GestureRecognizers>
                                            <TapGestureRecognizer/>
                                        </Frame.GestureRecognizers>
                                        <Button BackgroundColor="Red"
                                                Text="Delete"
                                                WidthRequest="90"
                                                HeightRequest="70"
                                                TextColor="{AppThemeBinding Dark=White}"
                                                FontSize="20"
                                                Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=RemoveCommand}"
                                                CommandParameter="{Binding .}"
                                                />
                                    </Frame>    
                                </SwipeItemView>
                                <!--SwipeItem Text="Delete"
                                           BackgroundColor="Red"
                                           Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=RemoveCommand}"
                                           CommandParameter="{Binding .}"/-->
                            </SwipeItems>
                            
                        </SwipeView.RightItems>
                        <Grid Padding="0.2">
                            <Frame BackgroundColor="{AppThemeBinding Dark=#FF303030}">
                                <Frame.GestureRecognizers>
                                    <TapGestureRecognizer CommandParameter="{Binding .}"
                                                          Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=GoToActualListCommand}"/>
                                </Frame.GestureRecognizers>
                                
                                <Label Text="{Binding Name}"
                                       FontSize="24"/>
                            </Frame>
                        </Grid>
                    </SwipeView>
                    
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
        <Button Text="+ NEUE LISTE "
                HeightRequest="60"
                Grid.Row="1"
                Grid.Column="1"
                FontSize="Medium"
                Margin="10"
                CornerRadius="50"
                BackgroundColor="{AppThemeBinding Dark=#FF303030, Light=SteelBlue}"
                TextColor="{AppThemeBinding Dark=LightSkyBlue, Light=White}"
                Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=GoToListCreatorCommand}"
                CommandParameter="{Binding .}">
            
        </Button>

    </Grid>

</ContentPage>

Solution

  • Solved the problem by writing [Ignore] above the list, so SQlite ignores it. So later you have to handle the list manually.

    using SQLite;
    
    namespace FinalShoppingList.Model
    {
        public class Liste
        {
            [PrimaryKey, AutoIncrement, NotNull]
            public int Id { get; set; }
    
            public string Name { get; set; }
    
            [Ignore]
            public List<Item> Items { get; set; } = new List<Item>();
        }
    
        public class Item
        {
            [PrimaryKey, AutoIncrement, NotNull]
            public int Id { get; set; }
            public string Name { get; set; }
            public int ListeId { get; set; }
        }
    }
    

    (I also changed the list from type string to object, and the object contains the string and more, but I think this was not relevant for solving the problem.)