Create a MAUI application using MVVM to implement a given model.
- Available on Android & IOS
- Work on ViewModel (views are not important)
Done:
- Champion list + navigation
- Champion detail
- Caracteristics management
- Champion management
- Swipe view (<MenuItem> because of Android problems)
- Skills management
- Skins management
NotDone:
- You can't remove a Skin
- You can't edit a Caracteristic
V2: MVVM_Toolkit
- .NET 7
- Android API 33 (tested)
- iOS 16 (tested)
Please note that the screenshots from the original app were taken with a different phone of the CloneApp ones.
Theses diagrams are not fully accurate and only gave the global idea of the conception.
Models
classDiagram
class LargeImage{
+/Base64 : string
}
class Champion{
+/Name : string
+/Bio : string
+/Icon : string
+/Characteristics : Dictionary(string, int)
~ AddSkin(skin : Skin) bool
~ RemoveSkin(skin: Skin) bool
+ AddSkill(skill: Skill) bool
+ RemoveSkill(skill: Skill) bool
+ AddCharacteristics(someCharacteristics : params Tuple(string, int)[])
+ RemoveCharacteristics(label : string) bool
+ this(label : string) : int?
}
Champion --> "1" LargeImage : Image
class ChampionClass{
<<enumeration>>
Unknown,
Assassin,
Fighter,
Mage,
Marksman,
Support,
Tank,
}
Champion --> "1" ChampionClass : Class
class Skin{
+/Name : string
+/Description : string
+/Icon : string
+/Price : float
}
Skin --> "1" LargeImage : Image
Champion "1" -- "*" Skin
class Skill{
+/Name : string
+/Description : string
}
class SkillType{
<<enumeration>>
Unknown,
Basic,
Passive,
Ultimate,
}
Skill --> "1" SkillType : Type
Champion --> "*" Skill
Every VM inherits from
BaseViewModel
which implementsINotifyPropertyChanged
andSetProperty
to notify the view of any changes and setting properties.
ViewModels
classDiagram
class AppVM {
+-/NavigateBackCommand : ICommand
+-/GoToChampionDetailCommand : ICommand
+-/GoToChampionSkinCommand : ICommand
+-/GoToAddChampionCommand : ICommand
+-/GoToEditChampionCommand : ICommand
+-/GoToAddSkinCommand : ICommand
+-/GoToEditSkinCommand : ICommand
+-/GoToAddSkillCommand : ICommand
+-/GoToEditSkillCommand : ICommand
+-/DeleteChampionCommand : ICommand
+-/AddChampionCommand : ICommand
+-/EditChampionCommand : ICommand
+-/AddSkinCommand : ICommand
+-/EditSkinCommand : ICommand
+-/AddSkillCommand : ICommand
+-/EditSkillCommand : ICommand
+-/ChooseImageCommand : ICommand
+-/ChooseIconCommand : ICommand
+-/ChooseSkinImageCommand : ICommand
+-/ChooseSkinIconCommand : ICommand
- NavigateBack() Task
- GoToChampionDetail(ChampionVM vm) Task
- GoToChampionSkin(SkinVM vm) Task
- GoToAddChampion() Task
- GoToEditChampion(ChampionVM vm) Task
- GoToAddSkin() Task
- GoToEditSkin(SkinVM vm) Task
- GoToAddSkill() Task
- GoToEditSkill(SkillVM vm) Task
- AddChampion(ChampionVM vm) Task
- EditChampion(ChampionVM vm) Task
- AddSkin(SkinVM vm) Task
- EditSkin(SkinVM vm) Task
- AddSkill(SkillVM vm) Task
- EditSkill(SkillVM vm) Task
- ChooseImage() Task
- ChooseIcon() Task
- ChooseSkinImage() Task
- ChooseSkinIcon() Task
}
AppVM --> "1" ChampionManagerVM : ChampionManagerVM
AppVM --> "1" AddOrEditChampionVM : AddOrEditChampionVM
AppVM --> "1" AddOrEditSkillVM : AddOrEditSkillVM
AppVM --> "1" AddOrEditSkinVM : AddOrEditSkinVM
class ChampionManagerVM {
+/Datamanager : IDataManager
+/Index : int
+_/HumanIndex : int
+_/IsFirstPage : int
+_/IsLastPage : int
+/Count : int
+/NbPages : int
+-/PreviousPageCommand : ICommand
+-/NextPageCommand : ICommand
+-/LoadChampionsCommand : ICommand
+-/DeleteChampionCommand : ICommand
+-/EditChampionCommand : ICommand
+-/AddChampionCommand : ICommand
- LoadChampions() Task
- LoadPage(bool) Task
+ DeleteChampion(ChampionVM vm) Task
+ EditChampion(ChampionVM vm) Task
+ AddChampion(ChampionVM vm) Task
}
ChampionManagerVM --> "1" ChampionVM : SelectedChampion
ChampionManagerVM --> "*" ChampionVM : Champions
class ChampionVM {
+/Model : Champion
+/Name : string
+/Bio : string
+/Icon : string
+/Image : string
+/Class : ChampionClass?
+ LoadStats()
+ AddStat()
+ RemoveStat()
+ LoadSkins()
+ AddSkin()
+ RemoveSkin()
+ UpdateSkin(Skin skin)
+ LoadSkills()
+ AddSkill()
+ RemoveSkill()
+ UpdateSkill(Skill skill)
}
ChampionVM --> "*" SkinVM : Skins
ChampionVM --> "*" SkillVM : Skills
ChampionVM --> "1" SkinVM : SelectedSkin
ChampionVM --> "1" SkillVM : SelectedSkill
class SkillVM {
+/Model : Skill
+/Name : string
+/Description : string
+_/Type : string
}
class SkinVM {
+/Model : Skin
+/Name : string
+/Description : string
+/Icon : string
+/Image : string
+/Price : float
}
class AddOrEditChampionVM {
+-/AddStatEditCommand : ICommand
+-/DeleteStatEditCommand : ICommand
+-/DeleteSkillEditCommand : ICommand
+/IsNewChamp : bool
+/EditName : string
+/RadioButton : string
+/Stat : String
+/StatValue : int
- AddStatEdit()
- RemoveStatEdit(string key)
- RemoveSkillEdit(SkillVM skill)
}
AddOrEditChampionVM ..|> ChampionVM
class AddOrEditSkillVM {
+/IsNewSkill : bool
+/EditName : string
+/SkillPicker : TypePicker
+/EditDesc : string
+_/SkillVM : SkillVM
}
AddOrEditSkillVM ..|> SkillVM
class AddOrEditSkinVM {
+/IsNewSkin : bool
+/EditName : string
+_/SkinVM : SkinVM
}
AddOrEditSkinVM ..|> SkinVM
Due to its youngness (and maybe certainly because of my lack of knowledge) the CollectionView, SwapView and others seems to have been implemented differently through the platforms leading to some issues.
For exemple this code works on Android but got problems of height on iOS
<CollectionView ItemsSource="{Binding SomeCollection}"
SelectionMode="None">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<SomeComponent/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
- Author: Valetin Clergue