Failing to pass a complex object from one page to another in .Net Maui - maui

I am trying to pass a complex object from MainPage to a ProductsPage, the object is a model with 4 class lists. Of the 4 class lists only 2 are passing data to the ProductsPage, the other 2 are not. I dont know where i am going wrong, i am using MVVM
My MainPageViewModel is as below
public partial class MainPageViewModel : BaseViewModel
{
public ObservableCollection<LogInModel> LogInModels { get; } = new();
public MainPageViewModel()
{
}
[ObservableProperty]
LogInModel logInModel;
[RelayCommand]
async Task GoToRetailAsync()
{
if (LogInModels.Count != 0)
LogInModels.Clear();
LogInModels.Add(logInModel);
await Shell.Current.GoToAsync($"{nameof(ProductsPage)}", true,
new Dictionary<string, object>
{
{"shiptoo",LogInModels[0].cat },
{"group",LogInModels[0].grp },
{"products",LogInModels[0].prod },
{"shipto",LogInModels[0].shp }
});
}
}
}
the failing class lists are shiptoo and group
Below is my ProductsViewModel
namespace Tenga.ViewModel
{
[QueryProperty("Products", "products")]
[QueryProperty("Group","group")]
[QueryProperty("Shiptoo","shiptoo")]
[QueryProperty("Shipto", "shipto")]
public partial class ProductsViewModel : BaseViewModel
{
public ProductsViewModel()
{
}
[ObservableProperty]
List<Shiptoo> shppp;
[ObservableProperty]
List<Group> groups;
[ObservableProperty]
List<Products> products;
[ObservableProperty]
List<Shipto> shipto;
}
}
Below is my LogInModel
namespace Tenga.Model
{
public class LogInModel
{
public string OTP { get; set; }
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
public string Balance { get; set; }
public string OpenToBuy { get; set; }
public string CreditLimit { get; set; }
public string LoginStatus { get; set; }
public string Error { get; set; }
public List<Shipto> shp = new List<Shipto>();
public List<Shiptoo> cat = new List<Shiptoo>();
public List<Group> grp = new List<Group>();
public List<Products> prod = new List<Products>();
}
public class Shipto
{
public string ShipCode { get; set; }
public string ShipDescription { get; set; }
}
public class Products
{
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
public string UOM { get; set; }
public string ConversionFactor { get; set; }
public string Category { get; set; }
public string Group { get; set; }
public byte[] Image { get; set; }
}
public class Shiptoo
{
public string ShipCode { get; set; }
public byte[] Image { get; set; }
}
public class Group
{
public string Category { get; set; }
public string Code { get; set; }
public byte[] Image { get; set; }
}
}
I have tried to review the class all seems alright, i have also tried changing the bindings and result is the same, can some one please help before go crazy

Implement IQueryAttributable in your ViewModel.
And use:
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
Model = query[nameof(MyModel )] as MyModel ;
}
Forget about those annotations. This is better. You cant mistake names, you can run code after/before they are set. I migrated all my code to use this.
Edit: While we are on the subject:
Instead of:
{"shiptoo",LogInModels[0].cat },
You should be using some constants. The name of the model usually. (Something like naming conventions when passing Extras in android, but much more simple).

Related

EF Core - hierarchy using Composite Design Pattern and CTE

I want to create a catalog products. There may be catalogs or products on each node.
I decided to use the composite design pattern.
I will download the node with the children using CTE. Unfortunately there was a problem, because EF Core doesn't add parentId in the CategoryProducts table.
Additionally the class (Category as my Composite) has its own CategoryDetails class, (Product as my Leaf) has its own ProductDetails class.
How do I configure EF Core to recursively get nodes from the tree?
Is CTE a good idea?
public enum CategoryProductType
{
Category,
Product
}
public abstract class CategoryProduct
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public CategoryProductType Type { get; private set; }
protected CategoryProduct(Guid id, string name, CategoryProductType type)
{
Id = id;
Name = name;
Type = type;
}
}
public class Category : CategoryProduct
{
public string Code { get; private set; }
public CategoryDetails CategoryDetails { get; private set; }
private ICollection<CategoryProduct> _children { get; set; } = new Collection<CategoryProduct>();
public IEnumerable<CategoryProduct> Children => _children;
public Category(Guid id, string name, string code)
: base(id, name, CategoryProductType.Category)
{
Code = code;
}
}
public class CategoryDetails
{
public Guid CategoryId { get; private set; }
public Category Category { get; private set; }
public string Description { get; private set; }
private CategoryDetails() { }
public CategoryDetails(Category category, string description)
{
Category = category);
Description = description);
}
}
public class Product : CategoryProduct
{
public string Index { get; private set; }
public ProductDetails ProductDetails { get; private set; }
public Product(Guid id, string name, string index)
: base(id, name, CategoryProductType.Product)
{
SetIndex(index);
}
}
EF Core Setting:
Unfortunately I don't know anything about CTE Recursion.
However, this is an example on how I modeled a hierarchical structure (i.e. a tree) with EF Core, hopefully it can help you.
public class TreeNode
{
public int TreeNodeId { get; private set; }
public int? ParentTreeNodeId { get; set; }
public TreeNode ParentTreeNode { get; set; }
public List<TreeNode> ChildrenTreeNodes { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TreeNode>(entity =>
{
entity.HasOne(n => n.ParentTreeNode)
.WithMany(n => n.ChildrenTreeNodes)
.HasForeignKey(n => n.ParentTreeNodeId);
});
}

One API call to retrieve all items in the model

I created a simple web api using Net Core 2.2. I have this api controller below, that gets one particular dungeon.
It is returning a dungeon as JSON, but it's not returning the MonsterList associated with the dungeon.
So this is my controller:
// GET: api/DungeonLists/5
[HttpGet("{id}")]
public async Task<ActionResult<DungeonList>> GetDungeonList(Guid id)
{
var dungeonList = await _context.DungeonList.FindAsync(id);
if (dungeonList == null)
{
return NotFound();
}
return dungeonList;
}
And here is my model for the Dungeon. As you can see, it has a MonsterList.
public partial class DungeonList
{
public DungeonList()
{
MonsterList = new HashSet<MonsterList>();
}
public Guid DungeonId { get; set; }
public string DungeonName { get; set; }
public string DungeonDesc { get; set; }
public string MapArea { get; set; }
public bool ShowProgress { get; set; }
public bool? DungeonResumable { get; set; }
public virtual ICollection<MonsterList> MonsterList { get; set; }
}
Here is my MonsterList model:
public partial class MonsterList
{
public string MonsterId { get; set; }
public Guid DungeonId { get; set; }
public string MonsterName { get; set; }
public byte? MonsterType { get; set; }
public bool IsBossMonster { get; set; }
public virtual DungeonList Dungeon { get; set; }
}
I want the JSON to also show the list of monsters associated with the dungeon.
Is there a way to do this? Or would I need to make a separate API call?
Thanks!
You need to change your code to the following:
[HttpGet("{id}")]
public async Task<ActionResult<DungeonList>> GetDungeonList(Guid id)
{
var dungeonList = await _context.DungeonList
.Include(i => i.MonsterList)
.FirstOrDefaultAsync(p => p.Id = id);
if (dungeonList == null)
{
return NotFound();
}
return dungeonList;
}
Additionally, since you arent using LazyLoading, you dont need the [virtual] on the MonsterList collection

how take details from a class

I have a method that gives me back all the films with a particular word inserted by user.
Now I want to copy all the details in one list so, when the user clicks a film that the app shows, it shows a toast with the corresponding ID.
How can i do this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace App_wrapper
{
public class Result1
{
public int vote_count { get; set; }
public int id { get; set; }
public bool video { get; set; }
public double vote_average { get; set; }
public string title { get; set; }
public double popularity { get; set; }
public string poster_path { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public List<int> genre_ids { get; set; }
public string backdrop_path { get; set; }
public bool adult { get; set; }
public string overview { get; set; }
public string release_date { get; set; }
}
public class RootObject
{
public int page { get; set; }
public int total_results { get; set; }
public int total_pages { get; set; }
public List<Result1> results { get; set; }
}
}
Try this
Public List<Film> filmList;
public class Film
{
private String title;
private String id;
public Film(String title, String id)
{
this.title = title;
this.id = id;
}
public String getId()
{
return id;
}
public override string ToString()
{
return title;
}
}
foreach (var paolo in toor.results)
{
var fItem=new Film{title=paolo.title,id=paolo.id}
filmList.Add(fItem);
}
RunOnUiThread(() =>
{
adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, filmList);
lv.Adapter = adapter;
});
//inside ListView_ItemClick
var id_film = filmList.ElementAt(e.Position).id;
For reference
how to use an ArrayAdapter in android of custom objects

LiteDB null reference on insert

I ran into this problem where in I get a null reference exception on insert.
I have two object Models UserInfo and UserConfig. On the first trial, UserConfig references a UserInfo instance
public class UserConfigObject : IUserConfig
{
BsonRef("userInfo")]
public IUserInfo UserInfo { get; set; }
public string AssignedJob { get; set; }
public string[] QueueItems { get; set; }
}
public class UserInfoObject : IUserInfo
{
[BsonId]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string IPAddress { get; set; }
}
And a method to insert the data into the database
public void AddUser(IUserConfig user)
{
var uconCollection = DatabaseInstance.GetCollection<IUserConfig>("userConfig");
var uinCollection = DatabaseInstance.GetCollection<IUserInfo>("userInfo");
uinCollection.Insert(user.UserInfo);
uconCollection.Insert(user);
}
This set up works fine but when I try to change the reference to UserInfo references UserConfig
public class UserInfoObject : IUserInfo
{
[BsonId]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string IPAddress { get; set; }
[BsonRef("userConfig")]
public IUserConfig UserConfig { get; set; }
}
public class UserConfigObject : IUserConfig
{
[BsonRef("userInfo")]
public IUserInfo UserInfo { get; set; }
[BsonId(true)]
public int ConfigID { get; set; }
public string AssignedJob { get; set; }
public string[] QueueItems { get; set; }
}
With a method call for
public void AddUser(IUserInfo user)
{
var uconCollection = DatabaseInstance.GetCollection<IUserConfig>("userConfig");
var uinCollection = DatabaseInstance.GetCollection<IUserInfo>("userInfo");
uconCollection.Insert(user.UserConfig);
uinCollection.Insert(user);
}
It no longer works, it throws an System.NullReferenceException: 'Object reference not set to an instance of an object.' on uinCollection.Insert(user);
Either v3 or v4, it doesn't work with the latter set up
Had the same problem but with collections. I've tried to save collection of invitations like so:
using var db = new LiteRepository(_connectionString);
var invitations = new List<Invitation>
{
// populate list
};
db.Insert(invitations);
The problem is that T parameter resolved as IEnumerable<Invitation> not just Invitation, so if you are inserting a collection, set type explicitly.
db.Insert<Invitation>(invitations);

Returning Entity with its children

Hi I am trying to return all vehicles with their recorded mileage through an api using ASP.Net Core with the following code:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.Include(m=>m.Mileages).ToList();
}
However this only returns the first vehicle with its mileages and not the others (there are five dummy vehicles in the db all with an initial mileage).
If I change the code to:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.ToList();
}
it returns the full list of vehicles but no mileage.
My class files are:
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<Mileage> Mileages { get; set; }
}
and
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
}
thanks for looking!
Tuppers
you can have them auto-load (lazy loading) using proxies... but for that, your foreign entities and collections must be marked virtual in your POCOs:
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public virtual ICollection<Mileage> Mileages { get; set; }
}
The proxy creation and lazy loading turned on, but that's the default in EF6.
https://msdn.microsoft.com/en-us/data/jj574232.aspx
Let me know if this works.
Well after a lot of searching I managed to find a solution. I used the following:
[HttpGet]
public IEnumerable<VehicleDto> Get()
{
var query = _context.Vehicles.Select(v => new VehicleDto
{
Registration = v.Registration,
Make = v.Make,
Model = v.Model,
Marked = v.Marked,
Mileages = v.Mileages.Select(m => new MileageDto
{
MileageDate = m.MileageDate,
RecordedMileage = m.RecordedMileage
})
.ToList(),
})
.ToList();
return (IEnumerable<VehicleDto>) query.AsEnumerable();
this doesn't seem to be the most elegant way of doing this, if anyone could offer any advice but it does return what is required.
The DTO's look like:
public class VehicleDto
{
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<MileageDto> Mileages { get; set; }
}
and
public class MileageDto
{
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
}
Thanks for taking the time to look at this
Tuppers