Search code examples
sqlitexamlxamarinxamarin-forms-4

how to access items from one model inside another when I save the items in xamarin forms


I am creating a project using sqlite in xamarin forms, I am experiencing a problem that, on the save new items page, I create an instance of my ITEM model and within the ITEM I reference another model which is PRIORITY, when I click on save items and I leave it in debug mode, I can receive all the items, including the saved PRIORITY, but within the variable where I add the items in SQLite it returns the PRIORITY as follows: ItemPriority = {CrudTasks.Models.Priority}

And when I try to access these items on the View Page I get no response.

//Function SaveItems
        private async void ExecuteSaveItemsCommand()
        {
            try
            {

                Item itemSaved = new Item
                {
                    Name = NameSave,
                    Description = DescriptionSave,
                    ItemPriority = new Priority()
                    {
                        PriorityName = PrioritySave,
                        PriorityColor = "#ccc"
                    }
                };

                _itemsService.InsertItem(itemSaved);
                ExecuteBackProductPageCommand();

            }
            catch (Exception ex)
            {
                await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
            }
        }
//Model Item
namespace CrudTarefas.Models
{
    [Table("Items")]
    public class Item
    {
        [PrimaryKey, AutoIncrement] 
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        [ManyToOne]
        public Priority ItemPriority { get; set; }
        
    }
}
//Model Priority
namespace CrudTarefas.Models
{
    [Table("Priorities")]
    public class Priority
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string PriorityName { get; set; }
        public string PriorityColor { get; set; }
    }
}

//CollectionView ListItemsPage
<ScrollView VerticalScrollBarVisibility="Never">
                <StackLayout>
                    <CollectionView ItemsSource="{Binding ItemsList}">
                        <CollectionView.ItemsLayout>
                            <LinearItemsLayout ItemSpacing="20" Orientation="Vertical" />
                        </CollectionView.ItemsLayout>
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <StackLayout>
                                    <Grid
                                        Margin="0,0,0,20"
                                        Padding="10"
                                        xct:CornerRadiusEffect.CornerRadius="12"
                                        BackgroundColor="{Binding ItemPriority.PriorityColor}"
                                        RowDefinitions="*,20,20"
                                        RowSpacing="10">
                                        <Frame
                                            Grid.Row="0"
                                            Padding="5"
                                            HorizontalOptions="Start">
                                            <Label Text="{Binding ItemPriority.PriorityName}" />
                                        </Frame>
                                        <Label
                                            Grid.Row="1"
                                            Text="{Binding Name}"
                                            TextColor="Black" />
                                        <Label
                                            Grid.Row="2"
                                            Text="{Binding Description}"
                                            TextColor="Black" />
                                    </Grid>
                                </StackLayout>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>
                </StackLayout>
            </ScrollView>
//Viewmodel ListItems
 -> In the LOADITEMS method in the commented code, I can access the static item with the collectionView

#region constructor
        public ListItemsViewmodel(INavigation navigation)
        {
            Navigation = navigation;
            _itemsService = new ItemsService();
            LoadItems();
            GoAddItemPageCommand = new Command(ExecuteGoAddItemPageCommand);
            LoadItemsCommand = new Command(ExecuteLoadItemsCommand);
        }
        #endregion

        #region commands 
        public ICommand GoAddItemPageCommand { get; set; }
        public ICommand LoadItemsCommand { get; set; }
        #endregion

        #region methods
  ->    private void LoadItems()
        {
            var items = _itemsService.GetAllItems();
            ItemsList = new ObservableCollection<Item>(items);

        }

I can't access another model's table


Solution

  • Based on your code, I created a demo and achieved this function on my side.

    You can try to modify your code as follows:

    1.add a foreign Key ( public int ItemId { get; set; }) for Priority.cs

     [Table("Priorities")]
    public class Priority
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string PriorityName { get; set; }
        public string PriorityColor { get; set; }
    
    
       [ForeignKey(typeof(Item))]
        public int ItemId { get; set; }
    }
    

    2.change [ManyToOne] to OneToOne for Item.cs

    [Table("Items")]
    public class Item
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    
        //add attribute  OneToOne
        [OneToOne]
        public Priority ItemPriority { get; set; }
       
    }
    

    3.add several methods(InsertPriority and UpdatePriority) for IItemsService.cs

       public interface IItemsService
       {
        List<Item> GetAllItems();
    
        void InsertItem(Item item);
    
        //add  method InsertPriority
        void InsertPriority(Priority item);
    
        //add  method UpdatePriority
        void UpdatePriority(Priority item);
    
        void UpdateItem(Item item);
        void DeleteItem(int id);
        bool ExistsItem(string name, string description, string priorityName);
       }
    

    4.implement above interface InsertPriority and UpdatePriority for class ItemsService.cs .

    And we also need to replace code var items = _connection.Table<Item>().ToList(); with code var items = _connection.GetAllWithChildren<Item>(); on method GetAllItems()

    public class ItemsService : IItemsService
    {
        private SQLiteConnection _connection;
    
        public ItemsService()
        {
            SetupDb();
        }
    
        private void SetupDb()
        {
            if(_connection == null)
            {
                string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ItemsDb.db3");
    
                _connection = new SQLiteConnection(dbPath);
                _connection.CreateTable<Item>();
                _connection.CreateTable<Priority>();
            }
        }
    
        public void InsertItem(Item item)
        {
            _connection.Insert(item);
        }
    
        public void UpdateItem(Item item)
        {
            // _connection.Update(item);
    
            // replace above code with the following code
            _connection.UpdateWithChildren(item);
        }
    
        public void DeleteItem(int id)
        {
            _connection.Delete(id);
        }
    
        public List<Item> GetAllItems()
        {
            //var items = _connection.Table<Item>().ToList();
    
             // replace above code with the following code
            var items = _connection.GetAllWithChildren<Item>();
    
            return items;
        }
    
        public bool ExistsItem(string name, string description, string priorityName)
        {
            var existsItem = _connection.Table<Item>().FirstOrDefault(it => it.Name == name && it.Description == description
            && it.ItemPriority.PriorityName == priorityName);
            return existsItem != null;
        }
    
    
        public void InsertPriority(Priority item)
        {
            _connection.Insert(item);
        }
    
        public void UpdatePriority(Priority item)
        {
            _connection.Update(item);
        }
    }
    

    5.modify command ExecuteSaveItemsCommand for AddItemViewmodel.cs

    public class AddItemViewmodel : BaseViewmodel
    {
       
      //For the sake of simplicity, omit the other codes
    
    
        #region methods
    
        //Function SaveItems
        private async void ExecuteSaveItemsCommand()
        {
            try
            {
    
                Item itemSaved = new Item()
                {
                    Name = NameSave,
                    Description = DescriptionSave,
                    //ItemPriority = new Priority
                    //{
                    //    PriorityName = PrioritySave,
                    //    PriorityColor = "#ccc"
                    //}
                };
    
                // _itemsService.InsertItem(itemSaved);
    
                Priority ItemPriority = new Priority
                {
                    PriorityName = PrioritySave,
    
                    PriorityColor = "#ccc"
                };
    
                _itemsService.InsertItem(itemSaved);
    
                _itemsService.InsertPriority(ItemPriority);
                itemSaved.ItemPriority = ItemPriority;
    
    
                _itemsService.UpdateItem(itemSaved);
                _itemsService.UpdatePriority(ItemPriority);
    
    
                ExecuteBackProductPageCommand();
    
            }
            catch (Exception ex)
            {
                await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
            }
        }
    
        private async void ExecuteBackProductPageCommand()
        {
            await Navigation.PopAsync();
        }
        #endregion
    }