@ -0,0 +1,256 @@ | |||||
# Created by https://www.gitignore.io/api/visualstudio | |||||
### VisualStudio ### | |||||
## Ignore Visual Studio temporary files, build results, and | |||||
## files generated by popular Visual Studio add-ons. | |||||
# User-specific files | |||||
*.suo | |||||
*.user | |||||
*.userosscache | |||||
*.sln.docstates | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | |||||
*.userprefs | |||||
# Build results | |||||
[Dd]ebug/ | |||||
[Dd]ebugPublic/ | |||||
[Rr]elease/ | |||||
[Rr]eleases/ | |||||
x64/ | |||||
x86/ | |||||
bld/ | |||||
[Bb]in/ | |||||
[Oo]bj/ | |||||
[Ll]og/ | |||||
# Visual Studio 2015 cache/options directory | |||||
.vs/ | |||||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||||
wwwroot/ | |||||
# MSTest test Results | |||||
[Tt]est[Rr]esult*/ | |||||
[Bb]uild[Ll]og.* | |||||
# NUNIT | |||||
*.VisualState.xml | |||||
TestResult.xml | |||||
# Build Results of an ATL Project | |||||
[Dd]ebugPS/ | |||||
[Rr]eleasePS/ | |||||
dlldata.c | |||||
# DNX | |||||
project.lock.json | |||||
project.fragment.lock.json | |||||
artifacts/ | |||||
*_i.c | |||||
*_p.c | |||||
*_i.h | |||||
*.ilk | |||||
*.meta | |||||
*.obj | |||||
*.pch | |||||
*.pdb | |||||
*.pgc | |||||
*.pgd | |||||
*.rsp | |||||
*.sbr | |||||
*.tlb | |||||
*.tli | |||||
*.tlh | |||||
*.tmp | |||||
*.tmp_proj | |||||
*.log | |||||
*.vspscc | |||||
*.vssscc | |||||
.builds | |||||
*.pidb | |||||
*.svclog | |||||
*.scc | |||||
# Chutzpah Test files | |||||
_Chutzpah* | |||||
# Visual C++ cache files | |||||
ipch/ | |||||
*.aps | |||||
*.ncb | |||||
*.opendb | |||||
*.opensdf | |||||
*.sdf | |||||
*.cachefile | |||||
*.VC.db | |||||
*.VC.VC.opendb | |||||
# Visual Studio profiler | |||||
*.psess | |||||
*.vsp | |||||
*.vspx | |||||
*.sap | |||||
# TFS 2012 Local Workspace | |||||
$tf/ | |||||
# Guidance Automation Toolkit | |||||
*.gpState | |||||
# ReSharper is a .NET coding add-in | |||||
_ReSharper*/ | |||||
*.[Rr]e[Ss]harper | |||||
*.DotSettings.user | |||||
# JustCode is a .NET coding add-in | |||||
.JustCode | |||||
# TeamCity is a build add-in | |||||
_TeamCity* | |||||
# DotCover is a Code Coverage Tool | |||||
*.dotCover | |||||
# NCrunch | |||||
_NCrunch_* | |||||
.*crunch*.local.xml | |||||
nCrunchTemp_* | |||||
# MightyMoose | |||||
*.mm.* | |||||
AutoTest.Net/ | |||||
# Web workbench (sass) | |||||
.sass-cache/ | |||||
# Installshield output folder | |||||
[Ee]xpress/ | |||||
# DocProject is a documentation generator add-in | |||||
DocProject/buildhelp/ | |||||
DocProject/Help/*.HxT | |||||
DocProject/Help/*.HxC | |||||
DocProject/Help/*.hhc | |||||
DocProject/Help/*.hhk | |||||
DocProject/Help/*.hhp | |||||
DocProject/Help/Html2 | |||||
DocProject/Help/html | |||||
# Click-Once directory | |||||
publish/ | |||||
# Publish Web Output | |||||
*.[Pp]ublish.xml | |||||
*.azurePubxml | |||||
# TODO: Comment the next line if you want to checkin your web deploy settings | |||||
# but database connection strings (with potential passwords) will be unencrypted | |||||
*.pubxml | |||||
*.publishproj | |||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to | |||||
# checkin your Azure Web App publish settings, but sensitive information contained | |||||
# in these scripts will be unencrypted | |||||
PublishScripts/ | |||||
# NuGet Packages | |||||
*.nupkg | |||||
# The packages folder can be ignored because of Package Restore | |||||
**/packages/* | |||||
# except build/, which is used as an MSBuild target. | |||||
!**/packages/build/ | |||||
# Uncomment if necessary however generally it will be regenerated when needed | |||||
#!**/packages/repositories.config | |||||
# NuGet v3's project.json files produces more ignoreable files | |||||
*.nuget.props | |||||
*.nuget.targets | |||||
# Microsoft Azure Build Output | |||||
csx/ | |||||
*.build.csdef | |||||
# Microsoft Azure Emulator | |||||
ecf/ | |||||
rcf/ | |||||
# Windows Store app package directories and files | |||||
AppPackages/ | |||||
BundleArtifacts/ | |||||
Package.StoreAssociation.xml | |||||
_pkginfo.txt | |||||
# Visual Studio cache files | |||||
# files ending in .cache can be ignored | |||||
*.[Cc]ache | |||||
# but keep track of directories ending in .cache | |||||
!*.[Cc]ache/ | |||||
# Others | |||||
ClientBin/ | |||||
~$* | |||||
*~ | |||||
*.dbmdl | |||||
*.dbproj.schemaview | |||||
*.pfx | |||||
*.publishsettings | |||||
node_modules/ | |||||
orleans.codegen.cs | |||||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||||
#bower_components/ | |||||
# RIA/Silverlight projects | |||||
Generated_Code/ | |||||
# Backup & report files from converting an old project file | |||||
# to a newer Visual Studio version. Backup files are not needed, | |||||
# because we have git ;-) | |||||
_UpgradeReport_Files/ | |||||
Backup*/ | |||||
UpgradeLog*.XML | |||||
UpgradeLog*.htm | |||||
# SQL Server files | |||||
*.mdf | |||||
*.ldf | |||||
# Business Intelligence projects | |||||
*.rdl.data | |||||
*.bim.layout | |||||
*.bim_*.settings | |||||
# Microsoft Fakes | |||||
FakesAssemblies/ | |||||
# GhostDoc plugin setting file | |||||
*.GhostDoc.xml | |||||
# Node.js Tools for Visual Studio | |||||
.ntvs_analysis.dat | |||||
# Visual Studio 6 build log | |||||
*.plg | |||||
# Visual Studio 6 workspace options file | |||||
*.opt | |||||
# Visual Studio LightSwitch build output | |||||
**/*.HTMLClient/GeneratedArtifacts | |||||
**/*.DesktopClient/GeneratedArtifacts | |||||
**/*.DesktopClient/ModelManifest.xml | |||||
**/*.Server/GeneratedArtifacts | |||||
**/*.Server/ModelManifest.xml | |||||
_Pvt_Extensions | |||||
# Paket dependency manager | |||||
.paket/paket.exe | |||||
paket-files/ | |||||
# FAKE - F# Make | |||||
.fake/ |
@ -0,0 +1,261 @@ | |||||
| |||||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
# Visual Studio 14 | |||||
VisualStudioVersion = 14.0.25420.1 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Droid", "eShopOnContainers\eShopOnContainers.Droid\eShopOnContainers.Droid.csproj", "{62DBB163-9CA9-4818-B48B-13233DF37C24}" | |||||
EndProject | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.iOS", "eShopOnContainers\eShopOnContainers.iOS\eShopOnContainers.iOS.csproj", "{6EEB23DC-7063-4444-9AF8-90DF24F549C0}" | |||||
EndProject | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Core", "eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{65116D1C-145B-4693-ABDA-F0FB6F425191}" | |||||
EndProject | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Windows", "eShopOnContainers\eShopOnContainers.Windows\eShopOnContainers.Windows.csproj", "{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}" | |||||
EndProject | |||||
Global | |||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU | |||||
Ad-Hoc|ARM = Ad-Hoc|ARM | |||||
Ad-Hoc|iPhone = Ad-Hoc|iPhone | |||||
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator | |||||
Ad-Hoc|x64 = Ad-Hoc|x64 | |||||
Ad-Hoc|x86 = Ad-Hoc|x86 | |||||
AppStore|Any CPU = AppStore|Any CPU | |||||
AppStore|ARM = AppStore|ARM | |||||
AppStore|iPhone = AppStore|iPhone | |||||
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator | |||||
AppStore|x64 = AppStore|x64 | |||||
AppStore|x86 = AppStore|x86 | |||||
Debug|Any CPU = Debug|Any CPU | |||||
Debug|ARM = Debug|ARM | |||||
Debug|iPhone = Debug|iPhone | |||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator | |||||
Debug|x64 = Debug|x64 | |||||
Debug|x86 = Debug|x86 | |||||
Release|Any CPU = Release|Any CPU | |||||
Release|ARM = Release|ARM | |||||
Release|iPhone = Release|iPhone | |||||
Release|iPhoneSimulator = Release|iPhoneSimulator | |||||
Release|x64 = Release|x64 | |||||
Release|x86 = Release|x86 | |||||
EndGlobalSection | |||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|ARM.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|ARM.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x64.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x64.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x86.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Ad-Hoc|x86.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|Any CPU.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|Any CPU.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|Any CPU.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|ARM.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|ARM.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|ARM.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhone.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhone.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhone.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x64.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x64.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x64.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x86.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x86.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.AppStore|x86.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|Any CPU.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|ARM.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|ARM.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|ARM.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhone.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhone.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhone.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x64.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x64.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x64.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x86.ActiveCfg = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x86.Build.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Debug|x86.Deploy.0 = Debug|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|Any CPU.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|ARM.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|ARM.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|ARM.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhone.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhone.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhone.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x64.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x64.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x64.Deploy.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x86.ActiveCfg = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x86.Build.0 = Release|Any CPU | |||||
{62DBB163-9CA9-4818-B48B-13233DF37C24}.Release|x86.Deploy.0 = Release|Any CPU | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|ARM.ActiveCfg = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|iPhone.ActiveCfg = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|iPhone.Build.0 = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|x64.ActiveCfg = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.AppStore|x86.ActiveCfg = AppStore|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|Any CPU.ActiveCfg = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|Any CPU.Build.0 = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|ARM.ActiveCfg = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|iPhone.ActiveCfg = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|iPhone.Build.0 = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|x64.ActiveCfg = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Debug|x86.ActiveCfg = Debug|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|Any CPU.ActiveCfg = Release|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|ARM.ActiveCfg = Release|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|iPhone.ActiveCfg = Release|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|iPhone.Build.0 = Release|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|x64.ActiveCfg = Release|iPhone | |||||
{6EEB23DC-7063-4444-9AF8-90DF24F549C0}.Release|x86.ActiveCfg = Release|iPhone | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|ARM.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|x64.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Ad-Hoc|x86.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|Any CPU.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|Any CPU.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|ARM.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|ARM.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|iPhone.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|iPhone.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|x64.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|x64.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|x86.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.AppStore|x86.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|ARM.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|ARM.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|iPhone.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|iPhone.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|x64.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|x64.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|x86.ActiveCfg = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Debug|x86.Build.0 = Debug|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|ARM.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|ARM.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|iPhone.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|iPhone.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|iPhoneSimulator.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|x64.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|x64.Build.0 = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|x86.ActiveCfg = Release|Any CPU | |||||
{65116D1C-145B-4693-ABDA-F0FB6F425191}.Release|x86.Build.0 = Release|Any CPU | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|Any CPU.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|Any CPU.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|Any CPU.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|ARM.ActiveCfg = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|ARM.Build.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|ARM.Deploy.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhone.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhone.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhone.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x64.ActiveCfg = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x64.Build.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x64.Deploy.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x86.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x86.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Ad-Hoc|x86.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|Any CPU.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|Any CPU.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|Any CPU.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|ARM.ActiveCfg = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|ARM.Build.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|ARM.Deploy.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhone.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhone.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhone.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhoneSimulator.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhoneSimulator.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|iPhoneSimulator.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x64.ActiveCfg = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x64.Build.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x64.Deploy.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x86.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x86.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.AppStore|x86.Deploy.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|Any CPU.ActiveCfg = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|Any CPU.Build.0 = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|Any CPU.Deploy.0 = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|ARM.ActiveCfg = Debug|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|ARM.Build.0 = Debug|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|ARM.Deploy.0 = Debug|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhone.ActiveCfg = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.ActiveCfg = Debug|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.Build.0 = Debug|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.Deploy.0 = Debug|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x86.ActiveCfg = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x86.Build.0 = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x86.Deploy.0 = Debug|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|Any CPU.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|ARM.ActiveCfg = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|ARM.Build.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|ARM.Deploy.0 = Release|ARM | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|iPhone.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|iPhoneSimulator.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x64.ActiveCfg = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x64.Build.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x64.Deploy.0 = Release|x64 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.ActiveCfg = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Build.0 = Release|x86 | |||||
{C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Release|x86.Deploy.0 = Release|x86 | |||||
EndGlobalSection | |||||
GlobalSection(SolutionProperties) = preSolution | |||||
HideSolutionNode = FALSE | |||||
EndGlobalSection | |||||
EndGlobal |
@ -0,0 +1,120 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Animations.Base | |||||
{ | |||||
public abstract class AnimationBase : BindableObject | |||||
{ | |||||
private bool _isRunning = false; | |||||
public static readonly BindableProperty TargetProperty = | |||||
BindableProperty.Create("Target", typeof(VisualElement), typeof(AnimationBase), null, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((AnimationBase)bindable).Target = (VisualElement)newValue); | |||||
public VisualElement Target | |||||
{ | |||||
get { return (VisualElement)GetValue(TargetProperty); } | |||||
set { SetValue(TargetProperty, value); } | |||||
} | |||||
public static readonly BindableProperty DurationProperty = | |||||
BindableProperty.Create("Duration", typeof(string), typeof(AnimationBase), "1000", | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((AnimationBase)bindable).Duration = (string)newValue); | |||||
public string Duration | |||||
{ | |||||
get { return (string)GetValue(DurationProperty); } | |||||
set { SetValue(DurationProperty, value); } | |||||
} | |||||
public static readonly BindableProperty EasingProperty = | |||||
BindableProperty.Create("Easing", typeof(EasingType), typeof(AnimationBase), EasingType.Linear, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((AnimationBase)bindable).Easing = (EasingType)newValue); | |||||
public EasingType Easing | |||||
{ | |||||
get { return (EasingType)GetValue(EasingProperty); } | |||||
set { SetValue(EasingProperty, value); } | |||||
} | |||||
public static readonly BindableProperty RepeatForeverProperty = | |||||
BindableProperty.Create("RepeatForever", typeof(bool), typeof(AnimationBase), false, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((AnimationBase)bindable).RepeatForever = (bool)newValue); | |||||
public bool RepeatForever | |||||
{ | |||||
get { return (bool)GetValue(RepeatForeverProperty); } | |||||
set { SetValue(RepeatForeverProperty, value); } | |||||
} | |||||
public static readonly BindableProperty DelayProperty = | |||||
BindableProperty.Create("Delay", typeof(int), typeof(AnimationBase), 0, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((AnimationBase)bindable).Delay = (int)newValue); | |||||
public int Delay | |||||
{ | |||||
get { return (int)GetValue(DelayProperty); } | |||||
set { SetValue(DelayProperty, value); } | |||||
} | |||||
protected abstract Task BeginAnimation(); | |||||
public async Task Begin() | |||||
{ | |||||
try | |||||
{ | |||||
if (!_isRunning) | |||||
{ | |||||
_isRunning = true; | |||||
await InternalBegin() | |||||
.ContinueWith(t => t.Exception, TaskContinuationOptions.OnlyOnFaulted) | |||||
.ConfigureAwait(false); | |||||
} | |||||
} | |||||
catch (TaskCanceledException) | |||||
{ | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Debug.WriteLine($"Exception in animation {ex}"); | |||||
} | |||||
} | |||||
protected abstract Task ResetAnimation(); | |||||
public async Task Reset() | |||||
{ | |||||
await ResetAnimation(); | |||||
} | |||||
private async Task InternalBegin() | |||||
{ | |||||
if (Delay > 0) | |||||
{ | |||||
await Task.Delay(Delay); | |||||
} | |||||
if (!RepeatForever) | |||||
{ | |||||
await BeginAnimation(); | |||||
} | |||||
else | |||||
{ | |||||
do | |||||
{ | |||||
await BeginAnimation(); | |||||
await ResetAnimation(); | |||||
} while (RepeatForever); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,17 @@ | |||||
namespace eShopOnContainers.Core.Animations.Base | |||||
{ | |||||
public enum EasingType | |||||
{ | |||||
BounceIn, | |||||
BounceOut, | |||||
CubicIn, | |||||
CubicInOut, | |||||
CubicOut, | |||||
Linear, | |||||
SinIn, | |||||
SinInOut, | |||||
SinOut, | |||||
SpringIn, | |||||
SpringOut | |||||
} | |||||
} |
@ -0,0 +1,163 @@ | |||||
using eShopOnContainers.Core.Animations.Base; | |||||
using eShopOnContainers.Core.Helpers; | |||||
using System; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Animations | |||||
{ | |||||
public class FadeToAnimation : AnimationBase | |||||
{ | |||||
public static readonly BindableProperty OpacityProperty = | |||||
BindableProperty.Create("Opacity", typeof(double), typeof(FadeToAnimation), 0.0d, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((FadeToAnimation)bindable).Opacity = (double)newValue); | |||||
public double Opacity | |||||
{ | |||||
get { return (double)GetValue(OpacityProperty); } | |||||
set { SetValue(OpacityProperty, value); } | |||||
} | |||||
protected override Task BeginAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Target.FadeTo(Opacity, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing)); | |||||
} | |||||
protected override Task ResetAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Target.FadeTo(0, 0, null); | |||||
} | |||||
} | |||||
public class FadeInAnimation : AnimationBase | |||||
{ | |||||
public enum FadeDirection | |||||
{ | |||||
Up, | |||||
Down | |||||
} | |||||
public static readonly BindableProperty DirectionProperty = | |||||
BindableProperty.Create("Direction", typeof(FadeDirection), typeof(FadeInAnimation), FadeDirection.Up, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((FadeInAnimation)bindable).Direction = (FadeDirection)newValue); | |||||
public FadeDirection Direction | |||||
{ | |||||
get { return (FadeDirection)GetValue(DirectionProperty); } | |||||
set { SetValue(DirectionProperty, value); } | |||||
} | |||||
protected override Task BeginAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Task.Run(() => | |||||
{ | |||||
Device.BeginInvokeOnMainThread(() => | |||||
{ | |||||
Target.Animate("FadeIn", FadeIn(), 16, Convert.ToUInt32(Duration)); | |||||
}); | |||||
}); | |||||
} | |||||
protected override Task ResetAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Target.FadeTo(0, 0, null); | |||||
} | |||||
internal Animation FadeIn() | |||||
{ | |||||
var animation = new Animation(); | |||||
animation.WithConcurrent((f) => Target.Opacity = f, 0, 1, Xamarin.Forms.Easing.CubicOut); | |||||
animation.WithConcurrent( | |||||
(f) => Target.TranslationY = f, | |||||
Target.TranslationY + ((Direction == FadeDirection.Up) ? 50 : -50), Target.TranslationY, | |||||
Xamarin.Forms.Easing.CubicOut, 0, 1); | |||||
return animation; | |||||
} | |||||
} | |||||
public class FadeOutAnimation : AnimationBase | |||||
{ | |||||
public enum FadeDirection | |||||
{ | |||||
Up, | |||||
Down | |||||
} | |||||
public static readonly BindableProperty DirectionProperty = | |||||
BindableProperty.Create("Direction", typeof(FadeDirection), typeof(FadeOutAnimation), FadeDirection.Up, | |||||
propertyChanged: (bindable, oldValue, newValue) => | |||||
((FadeOutAnimation)bindable).Direction = (FadeDirection)newValue); | |||||
public FadeDirection Direction | |||||
{ | |||||
get { return (FadeDirection)GetValue(DirectionProperty); } | |||||
set { SetValue(DirectionProperty, value); } | |||||
} | |||||
protected override Task BeginAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Task.Run(() => | |||||
{ | |||||
Device.BeginInvokeOnMainThread(() => | |||||
{ | |||||
Target.Animate("FadeOut", FadeOut(), 16, Convert.ToUInt32(Duration)); | |||||
}); | |||||
}); | |||||
} | |||||
protected override Task ResetAnimation() | |||||
{ | |||||
if (Target == null) | |||||
{ | |||||
throw new NullReferenceException("Null Target property."); | |||||
} | |||||
return Target.FadeTo(0, 0, null); | |||||
} | |||||
internal Animation FadeOut() | |||||
{ | |||||
var animation = new Animation(); | |||||
animation.WithConcurrent( | |||||
(f) => Target.Opacity = f, | |||||
1, 0); | |||||
animation.WithConcurrent( | |||||
(f) => Target.TranslationY = f, | |||||
Target.TranslationY, Target.TranslationY + ((Direction == FadeDirection.Up) ? 50 : -50)); | |||||
return animation; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,48 @@ | |||||
using eShopOnContainers.Core.Animations.Base; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Animations | |||||
{ | |||||
[ContentProperty("Animations")] | |||||
public class StoryBoard : AnimationBase | |||||
{ | |||||
public StoryBoard() | |||||
{ | |||||
Animations = new List<AnimationBase>(); | |||||
} | |||||
public StoryBoard(List<AnimationBase> animations) | |||||
{ | |||||
Animations = animations; | |||||
} | |||||
public List<AnimationBase> Animations | |||||
{ | |||||
get; | |||||
} | |||||
protected override async Task BeginAnimation() | |||||
{ | |||||
foreach (var animation in Animations) | |||||
{ | |||||
if (animation.Target == null) | |||||
animation.Target = Target; | |||||
await animation.Begin(); | |||||
} | |||||
} | |||||
protected override async Task ResetAnimation() | |||||
{ | |||||
foreach (var animation in Animations) | |||||
{ | |||||
if (animation.Target == null) | |||||
animation.Target = Target; | |||||
await animation.Reset(); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,140 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<Application xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light" | |||||
xmlns:converters="clr-namespace:eShopOnContainers.Core.Converters;assembly=eShopOnContainers.Core" | |||||
xmlns:effects="clr-namespace:eShopOnContainers.Core.Effects;assembly=eShopOnContainers.Core" | |||||
x:Class="eShopOnContainers.App"> | |||||
<Application.Resources> | |||||
<ResourceDictionary MergedWith="light:LightThemeResources"> | |||||
<!-- COLORS --> | |||||
<Color x:Key="WhiteColor">#ffffff</Color> | |||||
<Color x:Key="BlackColor">#000000</Color> | |||||
<Color x:Key="BackgroundColor">#F4F6FA</Color> | |||||
<Color x:Key="AccentColor">#00857D</Color> | |||||
<Color x:Key="LightGreenColor">#83D01B</Color> | |||||
<Color x:Key="GreenColor">#00A69C</Color> | |||||
<Color x:Key="DarkGreenColor">#00857D</Color> | |||||
<Color x:Key="GrayColor">#e2e2e2</Color> | |||||
<!-- FONTS --> | |||||
<OnPlatform | |||||
x:Key="MontserratRegular" | |||||
x:TypeArguments="x:String" | |||||
iOS="Montserrat-Regular" | |||||
Android="Montserrat-Regular.ttf#Montserrat" | |||||
WinPhone="Assets/Fonts/Montserrat-Regular.ttf#Montserrat"/> | |||||
<OnPlatform | |||||
x:Key="MontserratBold" | |||||
x:TypeArguments="x:String" | |||||
iOS="Montserrat-Bold" | |||||
Android="Montserrat-Bold.ttf#Montserrat" | |||||
WinPhone="Assets/Fonts/Montserrat-Bold.ttf#Montserrat"/> | |||||
<OnPlatform | |||||
x:Key="SourceSansProRegular" | |||||
x:TypeArguments="x:String" | |||||
iOS="SourceSansPro-Regular" | |||||
Android="SourceSansPro-Regular.ttf#Source Sans Pro" | |||||
WinPhone="Assets/Fonts/SourceSansPro-Regular.ttf#Source Sans Pro"/> | |||||
<!-- FONT SIZES --> | |||||
<OnPlatform | |||||
x:Key="LittleSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="11" | |||||
Android="12" | |||||
WinPhone="12"/> | |||||
<OnPlatform | |||||
x:Key="MidMediumSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="12" | |||||
Android="14" | |||||
WinPhone="14"/> | |||||
<OnPlatform | |||||
x:Key="MediumSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="14" | |||||
Android="16" | |||||
WinPhone="16"/> | |||||
<OnPlatform | |||||
x:Key="LargeSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="16" | |||||
Android="18" | |||||
WinPhone="18"/> | |||||
<OnPlatform | |||||
x:Key="LargerSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="18" | |||||
Android="20" | |||||
WinPhone="20"/> | |||||
<OnPlatform | |||||
x:Key="BigSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="20" | |||||
Android="24" | |||||
WinPhone="24"/> | |||||
<OnPlatform | |||||
x:Key="ExtraBigSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="24" | |||||
Android="32" | |||||
WinPhone="32"/> | |||||
<OnPlatform | |||||
x:Key="HugeSize" | |||||
x:TypeArguments="x:Double" | |||||
iOS="32" | |||||
Android="48" | |||||
WinPhone="48"/> | |||||
<!-- CONVERTERS --> | |||||
<converters:ToUpperConverter x:Key="ToUpperConverter" /> | |||||
<converters:DatetimeConverter x:Key="DatetimeConverter" /> | |||||
<!-- STYLES --> | |||||
<Style x:Key="EntryStyle" | |||||
TargetType="{x:Type Entry}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="PlaceholderColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LargeSize}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="FillAndExpand" /> | |||||
<Setter Property="FontAttributes" | |||||
Value="Bold" /> | |||||
<Setter Property="Opacity" | |||||
Value="0.6" /> | |||||
<Setter Property="effects:LineColorEffect.ApplyLineColor" | |||||
Value="True" /> | |||||
<Setter Property="effects:LineColorEffect.LineColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Style.Triggers> | |||||
<Trigger TargetType="Entry" | |||||
Property="IsFocused" | |||||
Value="True"> | |||||
<Setter Property="Opacity" Value="1" /> | |||||
</Trigger> | |||||
</Style.Triggers> | |||||
</Style> | |||||
<Style TargetType="NavigationPage"> | |||||
<Setter Property="BarBackgroundColor" Value="{StaticResource GreenColor}"/> | |||||
<Setter Property="BarTextColor" Value="{StaticResource WhiteColor}"/> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</Application.Resources> | |||||
</Application> |
@ -0,0 +1,48 @@ | |||||
using eShopOnContainers.Services; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Xaml; | |||||
[assembly: XamlCompilation(XamlCompilationOptions.Compile)] | |||||
namespace eShopOnContainers | |||||
{ | |||||
public partial class App : Application | |||||
{ | |||||
public App() | |||||
{ | |||||
InitializeComponent(); | |||||
if (Device.OS == TargetPlatform.Windows) | |||||
{ | |||||
InitNavigation(); | |||||
} | |||||
} | |||||
private Task InitNavigation() | |||||
{ | |||||
var navigationService = ViewModelLocator.Instance.Resolve<INavigationService>(); | |||||
return navigationService.InitializeAsync(); | |||||
} | |||||
protected override async void OnStart() | |||||
{ | |||||
base.OnStart(); | |||||
if (Device.OS != TargetPlatform.Windows) | |||||
{ | |||||
await InitNavigation(); | |||||
} | |||||
} | |||||
protected override void OnSleep() | |||||
{ | |||||
// Handle when your app sleeps | |||||
} | |||||
protected override void OnResume() | |||||
{ | |||||
// Handle when your app resumes | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,111 @@ | |||||
using System; | |||||
using System.Collections; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Controls | |||||
{ | |||||
public class BindablePicker : Picker | |||||
{ | |||||
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", | |||||
typeof(IEnumerable), typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged); | |||||
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", | |||||
typeof(object), typeof(BindablePicker), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged); | |||||
public BindablePicker() | |||||
{ | |||||
SelectedIndexChanged += (o, e) => | |||||
{ | |||||
if (SelectedIndex < 0 || ItemsSource == null || !ItemsSource.GetEnumerator().MoveNext()) | |||||
{ | |||||
SelectedItem = null; | |||||
return; | |||||
} | |||||
var index = 0; | |||||
foreach (var item in ItemsSource) | |||||
{ | |||||
if (index == SelectedIndex) | |||||
{ | |||||
SelectedItem = item; | |||||
break; | |||||
} | |||||
index++; | |||||
} | |||||
}; | |||||
} | |||||
public IEnumerable ItemsSource | |||||
{ | |||||
get { return (IEnumerable)GetValue(ItemsSourceProperty); } | |||||
set { SetValue(ItemsSourceProperty, value); } | |||||
} | |||||
public Object SelectedItem | |||||
{ | |||||
get { return GetValue(SelectedItemProperty); } | |||||
set | |||||
{ | |||||
if (SelectedItem != value) | |||||
{ | |||||
SetValue(SelectedItemProperty, value); | |||||
InternalUpdateSelectedIndex(); | |||||
} | |||||
} | |||||
} | |||||
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected; | |||||
private void InternalUpdateSelectedIndex() | |||||
{ | |||||
var selectedIndex = -1; | |||||
if (ItemsSource != null) | |||||
{ | |||||
var index = 0; | |||||
foreach (var item in ItemsSource) | |||||
{ | |||||
string strItem = item?.ToString(); | |||||
if (item != null && SelectedItem != null | |||||
&& !string.IsNullOrEmpty(strItem) | |||||
&& item.ToString().Equals(SelectedItem.ToString())) | |||||
{ | |||||
selectedIndex = index; | |||||
break; | |||||
} | |||||
index++; | |||||
} | |||||
} | |||||
SelectedIndex = selectedIndex; | |||||
} | |||||
private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue) | |||||
{ | |||||
var boundPicker = (BindablePicker)bindable; | |||||
if (Equals(newValue, null) && !Equals(oldValue, null)) | |||||
return; | |||||
boundPicker.Items.Clear(); | |||||
if (!Equals(newValue, null)) | |||||
{ | |||||
foreach (var item in (IEnumerable)newValue) | |||||
boundPicker.Items.Add(item.ToString()); | |||||
} | |||||
boundPicker.InternalUpdateSelectedIndex(); | |||||
} | |||||
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue) | |||||
{ | |||||
var boundPicker = (BindablePicker)bindable; | |||||
if (boundPicker.ItemSelected != null) | |||||
{ | |||||
boundPicker.ItemSelected(boundPicker, new SelectedItemChangedEventArgs(newValue)); | |||||
} | |||||
boundPicker.InternalUpdateSelectedIndex(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,35 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Controls | |||||
{ | |||||
public class CustomTabbedPage : TabbedPage | |||||
{ | |||||
public static BindableProperty BadgeTextProperty = | |||||
BindableProperty.CreateAttached("BadgeText", typeof(string), typeof(CustomTabbedPage), default(string), | |||||
BindingMode.OneWay); | |||||
public static BindableProperty BadgeColorProperty = | |||||
BindableProperty.CreateAttached("BadgeColor", typeof(Color), typeof(CustomTabbedPage), Color.Default, | |||||
BindingMode.OneWay); | |||||
public static string GetBadgeText(BindableObject view) | |||||
{ | |||||
return (string)view.GetValue(BadgeTextProperty); | |||||
} | |||||
public static void SetBadgeText(BindableObject view, string value) | |||||
{ | |||||
view.SetValue(BadgeTextProperty, value); | |||||
} | |||||
public static Color GetBadgeColor(BindableObject view) | |||||
{ | |||||
return (Color)view.GetValue(BadgeColorProperty); | |||||
} | |||||
public static void SetBadgeColor(BindableObject view, Color value) | |||||
{ | |||||
view.SetValue(BadgeColorProperty, value); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,26 @@ | |||||
using System; | |||||
using System.Globalization; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Converters | |||||
{ | |||||
public class DatetimeConverter : IValueConverter | |||||
{ | |||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
if(value is DateTime) | |||||
{ | |||||
var date = (DateTime)value; | |||||
return date.ToString("MMMM dd yyyy").ToUpper(); | |||||
} | |||||
return value; | |||||
} | |||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
using System; | |||||
using System.Globalization; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Converters | |||||
{ | |||||
public class ToUpperConverter : IValueConverter | |||||
{ | |||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
return value.ToString().ToUpperInvariant(); | |||||
} | |||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,67 @@ | |||||
using System.Linq; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Effects | |||||
{ | |||||
public static class LineColorEffect | |||||
{ | |||||
public static readonly BindableProperty ApplyLineColorProperty = | |||||
BindableProperty.CreateAttached("ApplyLineColor", typeof(bool), typeof(LineColorEffect), false, | |||||
propertyChanged: OnApplyLineColorChanged); | |||||
public static bool GetApplyLineColor(BindableObject view) | |||||
{ | |||||
return (bool)view.GetValue(ApplyLineColorProperty); | |||||
} | |||||
public static void SetApplyLineColor(BindableObject view, bool value) | |||||
{ | |||||
view.SetValue(ApplyLineColorProperty, value); | |||||
} | |||||
private static void OnApplyLineColorChanged(BindableObject bindable, object oldValue, object newValue) | |||||
{ | |||||
var view = bindable as View; | |||||
if (view == null) | |||||
{ | |||||
return; | |||||
} | |||||
bool hasShadow = (bool)newValue; | |||||
if (hasShadow) | |||||
{ | |||||
view.Effects.Add(new EntryLineColorEffect()); | |||||
} | |||||
else | |||||
{ | |||||
var entryLineColorEffectToRemove = view.Effects.FirstOrDefault(e => e is EntryLineColorEffect); | |||||
if (entryLineColorEffectToRemove != null) | |||||
{ | |||||
view.Effects.Remove(entryLineColorEffectToRemove); | |||||
} | |||||
} | |||||
} | |||||
public static readonly BindableProperty LineColorProperty = | |||||
BindableProperty.CreateAttached("LineColor", typeof(Color), typeof(LineColorEffect), Color.Default); | |||||
public static Color GetLineColor(BindableObject view) | |||||
{ | |||||
return (Color)view.GetValue(LineColorProperty); | |||||
} | |||||
public static void SetLineColor(BindableObject view, Color value) | |||||
{ | |||||
view.SetValue(LineColorProperty, value); | |||||
} | |||||
class EntryLineColorEffect : RoutingEffect | |||||
{ | |||||
public EntryLineColorEffect() : base("BikeSharing.EntryLineColorEffect") | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,18 @@ | |||||
using eShopOnContainers.Core.Animations.Base; | |||||
using System; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Extensions | |||||
{ | |||||
public static class AnimationExtension | |||||
{ | |||||
public static async void Animate(this VisualElement visualElement, AnimationBase animation, Action onFinishedCallback = null) | |||||
{ | |||||
animation.Target = visualElement; | |||||
await animation.Begin(); | |||||
onFinishedCallback?.Invoke(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,39 @@ | |||||
using eShopOnContainers.Core.Animations.Base; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Helpers | |||||
{ | |||||
public static class EasingHelper | |||||
{ | |||||
public static Easing GetEasing(EasingType type) | |||||
{ | |||||
switch (type) | |||||
{ | |||||
case EasingType.BounceIn: | |||||
return Easing.BounceIn; | |||||
case EasingType.BounceOut: | |||||
return Easing.BounceOut; | |||||
case EasingType.CubicIn: | |||||
return Easing.CubicIn; | |||||
case EasingType.CubicInOut: | |||||
return Easing.CubicInOut; | |||||
case EasingType.CubicOut: | |||||
return Easing.CubicOut; | |||||
case EasingType.Linear: | |||||
return Easing.Linear; | |||||
case EasingType.SinIn: | |||||
return Easing.SinIn; | |||||
case EasingType.SinInOut: | |||||
return Easing.SinInOut; | |||||
case EasingType.SinOut: | |||||
return Easing.SinOut; | |||||
case EasingType.SpringIn: | |||||
return Easing.SpringIn; | |||||
case EasingType.SpringOut: | |||||
return Easing.SpringOut; | |||||
} | |||||
return null; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,12 @@ | |||||
using System; | |||||
namespace eShopOnContainers.Core.Models.Orders | |||||
{ | |||||
public class Order | |||||
{ | |||||
public long OrderNumber { get; set; } | |||||
public double Total { get; set; } | |||||
public DateTime Date { get; set; } | |||||
public OrderStatus Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,10 @@ | |||||
namespace eShopOnContainers.Core.Models.Orders | |||||
{ | |||||
public enum OrderStatus | |||||
{ | |||||
Pending, | |||||
WareHouse, | |||||
Delivered, | |||||
Lost | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
namespace eShopOnContainers.Core.Models.Products | |||||
{ | |||||
public class Product | |||||
{ | |||||
public string Name { get; set; } | |||||
public string Image { get; set; } | |||||
public double Price { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,30 @@ | |||||
using System.Resources; | |||||
using System.Reflection; | |||||
using System.Runtime.CompilerServices; | |||||
using System.Runtime.InteropServices; | |||||
// General Information about an assembly is controlled through the following | |||||
// set of attributes. Change these attribute values to modify the information | |||||
// associated with an assembly. | |||||
[assembly: AssemblyTitle("eShopOnContainers")] | |||||
[assembly: AssemblyDescription("")] | |||||
[assembly: AssemblyConfiguration("")] | |||||
[assembly: AssemblyCompany("")] | |||||
[assembly: AssemblyProduct("eShopOnContainers")] | |||||
[assembly: AssemblyCopyright("Copyright © 2016")] | |||||
[assembly: AssemblyTrademark("")] | |||||
[assembly: AssemblyCulture("")] | |||||
[assembly: NeutralResourcesLanguage("en")] | |||||
// Version information for an assembly consists of the following four values: | |||||
// | |||||
// Major Version | |||||
// Minor Version | |||||
// Build Number | |||||
// Revision | |||||
// | |||||
// You can specify all the values or you can default the Build and Revision Numbers | |||||
// by using the '*' as shown below: | |||||
// [assembly: AssemblyVersion("1.0.*")] | |||||
[assembly: AssemblyVersion("1.0.0.0")] | |||||
[assembly: AssemblyFileVersion("1.0.0.0")] |
@ -0,0 +1,13 @@ | |||||
using Acr.UserDialogs; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Services | |||||
{ | |||||
public class DialogService : IDialogService | |||||
{ | |||||
public Task ShowAlertAsync(string message, string title, string buttonLabel) | |||||
{ | |||||
return UserDialogs.Instance.AlertAsync(message, title, buttonLabel); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Services | |||||
{ | |||||
public interface IDialogService | |||||
{ | |||||
Task ShowAlertAsync(string message, string title, string buttonLabel); | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Services | |||||
{ | |||||
public interface INavigationService | |||||
{ | |||||
Task InitializeAsync(); | |||||
Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase; | |||||
Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase; | |||||
Task NavigateToAsync(Type viewModelType); | |||||
Task NavigateToAsync(Type viewModelType, object parameter); | |||||
Task NavigateBackAsync(); | |||||
Task RemoveLastFromBackStackAsync(); | |||||
Task RemoveBackStackAsync(); | |||||
} | |||||
} |
@ -0,0 +1,159 @@ | |||||
using eShopOnContainers.Core.ViewModels; | |||||
using eShopOnContainers.Core.Views; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Services | |||||
{ | |||||
public class NavigationService : INavigationService | |||||
{ | |||||
protected readonly Dictionary<Type, Type> _mappings; | |||||
protected Application CurrentApplication | |||||
{ | |||||
get | |||||
{ | |||||
return Application.Current; | |||||
} | |||||
} | |||||
public NavigationService() | |||||
{ | |||||
_mappings = new Dictionary<Type, Type>(); | |||||
CreatePageViewModelMappings(); | |||||
} | |||||
public Task InitializeAsync() | |||||
{ | |||||
return NavigateToAsync<LoginViewModel>(); | |||||
} | |||||
public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase | |||||
{ | |||||
return InternalNavigateToAsync(typeof(TViewModel), null); | |||||
} | |||||
public Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase | |||||
{ | |||||
return InternalNavigateToAsync(typeof(TViewModel), parameter); | |||||
} | |||||
public Task NavigateToAsync(Type viewModelType) | |||||
{ | |||||
return InternalNavigateToAsync(viewModelType, null); | |||||
} | |||||
public Task NavigateToAsync(Type viewModelType, object parameter) | |||||
{ | |||||
return InternalNavigateToAsync(viewModelType, parameter); | |||||
} | |||||
public async Task NavigateBackAsync() | |||||
{ | |||||
if (CurrentApplication.MainPage is HomeView) | |||||
{ | |||||
var mainPage = CurrentApplication.MainPage as HomeView; | |||||
await mainPage.Navigation.PopAsync(); | |||||
} | |||||
else if (CurrentApplication.MainPage != null) | |||||
{ | |||||
await CurrentApplication.MainPage.Navigation.PopAsync(); | |||||
} | |||||
} | |||||
public virtual Task RemoveLastFromBackStackAsync() | |||||
{ | |||||
var mainPage = CurrentApplication.MainPage as CustomNavigationPage; | |||||
if (mainPage != null) | |||||
{ | |||||
mainPage.Navigation.RemovePage( | |||||
mainPage.Navigation.NavigationStack[mainPage.Navigation.NavigationStack.Count - 2]); | |||||
} | |||||
return Task.FromResult(true); | |||||
} | |||||
public virtual Task RemoveBackStackAsync() | |||||
{ | |||||
var mainPage = CurrentApplication.MainPage as CustomNavigationPage; | |||||
if (mainPage != null) | |||||
{ | |||||
for (int i = 0; i < mainPage.Navigation.NavigationStack.Count - 1; i++) | |||||
{ | |||||
var page = mainPage.Navigation.NavigationStack[i]; | |||||
mainPage.Navigation.RemovePage(page); | |||||
} | |||||
} | |||||
return Task.FromResult(true); | |||||
} | |||||
protected virtual async Task InternalNavigateToAsync(Type viewModelType, object parameter) | |||||
{ | |||||
Page page = CreateAndBindPage(viewModelType, parameter); | |||||
if (page is LoginView) | |||||
{ | |||||
CurrentApplication.MainPage = new CustomNavigationPage(page); | |||||
} | |||||
else | |||||
{ | |||||
var navigationPage = CurrentApplication.MainPage as CustomNavigationPage; | |||||
if (navigationPage != null) | |||||
{ | |||||
await navigationPage.PushAsync(page); | |||||
} | |||||
else | |||||
{ | |||||
CurrentApplication.MainPage = new CustomNavigationPage(page); | |||||
} | |||||
} | |||||
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter); | |||||
} | |||||
protected Type GetPageTypeForViewModel(Type viewModelType) | |||||
{ | |||||
if (!_mappings.ContainsKey(viewModelType)) | |||||
{ | |||||
throw new KeyNotFoundException($"No map for ${viewModelType} was found on navigation mappings"); | |||||
} | |||||
return _mappings[viewModelType]; | |||||
} | |||||
protected Page CreateAndBindPage(Type viewModelType, object parameter) | |||||
{ | |||||
Type pageType = GetPageTypeForViewModel(viewModelType); | |||||
if (pageType == null) | |||||
{ | |||||
throw new Exception($"Mapping type for {viewModelType} is not a page"); | |||||
} | |||||
Page page = Activator.CreateInstance(pageType) as Page; | |||||
ViewModelBase viewModel = ViewModelLocator.Instance.Resolve(viewModelType) as ViewModelBase; | |||||
page.BindingContext = viewModel; | |||||
return page; | |||||
} | |||||
private void CreatePageViewModelMappings() | |||||
{ | |||||
_mappings.Add(typeof(CartViewModel), typeof(CartView)); | |||||
_mappings.Add(typeof(ProductsViewModel), typeof(HomeView)); | |||||
_mappings.Add(typeof(LoginViewModel), typeof(LoginView)); | |||||
_mappings.Add(typeof(MainViewModel), typeof(MainView)); | |||||
_mappings.Add(typeof(OrderDetailViewModel), typeof(OrderDetailView)); | |||||
_mappings.Add(typeof(OrdersViewModel), typeof(OrdersView)); | |||||
_mappings.Add(typeof(ProfileViewModel), typeof(ProfileView)); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,29 @@ | |||||
using eShopOnContainers.Core.Models.Orders; | |||||
using System; | |||||
using System.Collections.ObjectModel; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Core.Services.Orders | |||||
{ | |||||
public class FakeOrdersService : IOrdersService | |||||
{ | |||||
public async Task<ObservableCollection<Order>> GetOrdersAsync() | |||||
{ | |||||
await Task.Delay(500); | |||||
return new ObservableCollection<Order> | |||||
{ | |||||
new Order { OrderNumber = 0123456789, Total = 45.30, Date = DateTime.Now, Status = OrderStatus.Delivered }, | |||||
new Order { OrderNumber = 9123456780, Total = 39.95, Date = DateTime.Now, Status = OrderStatus.Delivered }, | |||||
new Order { OrderNumber = 8765432190, Total = 15.00, Date = DateTime.Now, Status = OrderStatus.Delivered }, | |||||
}; | |||||
} | |||||
public async Task<Order> GetCartAsync() | |||||
{ | |||||
await Task.Delay(500); | |||||
return new Order { OrderNumber = 0123456789, Total = 45.99, Date = DateTime.Now, Status = OrderStatus.Pending }; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,13 @@ | |||||
using eShopOnContainers.Core.Models.Orders; | |||||
using System.Collections.ObjectModel; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Core.Services.Orders | |||||
{ | |||||
public interface IOrdersService | |||||
{ | |||||
Task<ObservableCollection<Order>> GetOrdersAsync(); | |||||
Task<Order> GetCartAsync(); | |||||
} | |||||
} |
@ -0,0 +1,22 @@ | |||||
using eShopOnContainers.Core.Models.Products; | |||||
using System.Collections.ObjectModel; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Services.Products | |||||
{ | |||||
public class FakeProductsService : IProductsService | |||||
{ | |||||
public async Task<ObservableCollection<Product>> GetProductsAsync() | |||||
{ | |||||
await Task.Delay(500); | |||||
return new ObservableCollection<Product> | |||||
{ | |||||
new Product { Image = Device.OS != TargetPlatform.Windows ? "fake_product_01" : "Assets/fake_product_01.png", Name = ".NET Bot Blue Sweatshirt (M)", Price = 19.50 }, | |||||
new Product { Image = Device.OS != TargetPlatform.Windows ? "fake_product_02": "Assets/fake_product_02.png", Name = ".NET Bot Purple Sweatshirt (M)", Price = 19.50 }, | |||||
new Product { Image = Device.OS != TargetPlatform.Windows ? "fake_product_03": "Assets/fake_product_03.png", Name = ".NET Bot Black Sweatshirt (M)", Price = 19.95 } | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,11 @@ | |||||
using eShopOnContainers.Core.Models.Products; | |||||
using System.Collections.ObjectModel; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.Core.Services.Products | |||||
{ | |||||
public interface IProductsService | |||||
{ | |||||
Task<ObservableCollection<Product>> GetProductsAsync(); | |||||
} | |||||
} |
@ -0,0 +1,16 @@ | |||||
using eShopOnContainers.Core.Animations.Base; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Triggers | |||||
{ | |||||
public class BeginAnimation : TriggerAction<VisualElement> | |||||
{ | |||||
public AnimationBase Animation { get; set; } | |||||
protected override async void Invoke(VisualElement sender) | |||||
{ | |||||
if (Animation != null) | |||||
await Animation.Begin(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
namespace eShopOnContainers.Core.Validations | |||||
{ | |||||
public interface IValidationRule<T> | |||||
{ | |||||
string ValidationMessage { get; set; } | |||||
bool Check(T value); | |||||
} | |||||
} |
@ -0,0 +1,7 @@ | |||||
namespace eShopOnContainers.Core.Validations | |||||
{ | |||||
public interface IValidity | |||||
{ | |||||
bool IsValid { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
namespace eShopOnContainers.Core.Validations | |||||
{ | |||||
public class IsNotNullOrEmptyRule<T> : IValidationRule<T> | |||||
{ | |||||
public string ValidationMessage { get; set; } | |||||
public bool Check(T value) | |||||
{ | |||||
if (value == null) | |||||
{ | |||||
return false; | |||||
} | |||||
var str = value as string; | |||||
return !string.IsNullOrWhiteSpace(str); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,72 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System.Collections.Generic; | |||||
using System.Collections.ObjectModel; | |||||
using System.Linq; | |||||
namespace eShopOnContainers.Core.Validations | |||||
{ | |||||
public class ValidatableObject<T> : ExtendedBindableObject, IValidity | |||||
{ | |||||
private readonly List<IValidationRule<T>> _validations; | |||||
private readonly ObservableCollection<string> _errors; | |||||
private T _value; | |||||
private bool _isValid; | |||||
public List<IValidationRule<T>> Validations => _validations; | |||||
public ObservableCollection<string> Errors => _errors; | |||||
public T Value | |||||
{ | |||||
get | |||||
{ | |||||
return _value; | |||||
} | |||||
set | |||||
{ | |||||
_value = value; | |||||
RaisePropertyChanged(() => Value); | |||||
} | |||||
} | |||||
public bool IsValid | |||||
{ | |||||
get | |||||
{ | |||||
return _isValid; | |||||
} | |||||
set | |||||
{ | |||||
_isValid = value; | |||||
_errors.Clear(); | |||||
RaisePropertyChanged(() => IsValid); | |||||
} | |||||
} | |||||
public ValidatableObject() | |||||
{ | |||||
_isValid = true; | |||||
_errors = new ObservableCollection<string>(); | |||||
_validations = new List<IValidationRule<T>>(); | |||||
} | |||||
public bool Validate() | |||||
{ | |||||
Errors.Clear(); | |||||
IEnumerable<string> errors = _validations.Where(v => !v.Check(Value)) | |||||
.Select(v => v.ValidationMessage); | |||||
foreach (var error in errors) | |||||
{ | |||||
Errors.Add(error); | |||||
} | |||||
IsValid = !Errors.Any(); | |||||
return this.IsValid; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,32 @@ | |||||
using System; | |||||
using System.Linq.Expressions; | |||||
using System.Reflection; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.ViewModels.Base | |||||
{ | |||||
public abstract class ExtendedBindableObject : BindableObject | |||||
{ | |||||
public void RaisePropertyChanged<T>(Expression<Func<T>> property) | |||||
{ | |||||
var name = GetMemberInfo(property).Name; | |||||
OnPropertyChanged(name); | |||||
} | |||||
private MemberInfo GetMemberInfo(Expression expression) | |||||
{ | |||||
MemberExpression operand; | |||||
LambdaExpression lambdaExpression = (LambdaExpression)expression; | |||||
if (lambdaExpression.Body as UnaryExpression != null) | |||||
{ | |||||
UnaryExpression body = (UnaryExpression)lambdaExpression.Body; | |||||
operand = (MemberExpression)body.Operand; | |||||
} | |||||
else | |||||
{ | |||||
operand = (MemberExpression)lambdaExpression.Body; | |||||
} | |||||
return operand.Member; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,8 @@ | |||||
namespace eShopOnContainers.Core.ViewModels.Base | |||||
{ | |||||
public class MessengerKeys | |||||
{ | |||||
// Add product to cart | |||||
public const string AddProduct = "AddProduct"; | |||||
} | |||||
} |
@ -0,0 +1,38 @@ | |||||
using eShopOnContainers.Services; | |||||
using System.Threading.Tasks; | |||||
namespace eShopOnContainers.ViewModels.Base | |||||
{ | |||||
public abstract class ViewModelBase : ExtendedBindableObject | |||||
{ | |||||
protected readonly IDialogService DialogService; | |||||
protected readonly INavigationService NavigationService; | |||||
private bool _isBusy; | |||||
public bool IsBusy | |||||
{ | |||||
get | |||||
{ | |||||
return _isBusy; | |||||
} | |||||
set | |||||
{ | |||||
_isBusy = value; | |||||
RaisePropertyChanged(() => IsBusy); | |||||
} | |||||
} | |||||
public ViewModelBase() | |||||
{ | |||||
DialogService = ViewModelLocator.Instance.Resolve<IDialogService>(); | |||||
NavigationService = ViewModelLocator.Instance.Resolve<INavigationService>(); | |||||
} | |||||
public virtual Task InitializeAsync(object navigationData) | |||||
{ | |||||
return Task.FromResult(false); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,69 @@ | |||||
using Microsoft.Practices.Unity; | |||||
using eShopOnContainers.Core.Services.Orders; | |||||
using eShopOnContainers.Core.Services.Products; | |||||
using eShopOnContainers.Core.ViewModels; | |||||
using eShopOnContainers.Services; | |||||
using System; | |||||
namespace eShopOnContainers.ViewModels.Base | |||||
{ | |||||
public class ViewModelLocator | |||||
{ | |||||
private readonly IUnityContainer _unityContainer; | |||||
private static readonly ViewModelLocator _instance = new ViewModelLocator(); | |||||
public static ViewModelLocator Instance | |||||
{ | |||||
get | |||||
{ | |||||
return _instance; | |||||
} | |||||
} | |||||
protected ViewModelLocator() | |||||
{ | |||||
_unityContainer = new UnityContainer(); | |||||
// services | |||||
_unityContainer.RegisterType<IDialogService, DialogService>(); | |||||
RegisterSingleton<INavigationService, NavigationService>(); | |||||
_unityContainer.RegisterType<IProductsService, FakeProductsService>(); | |||||
_unityContainer.RegisterType<IOrdersService, FakeOrdersService>(); | |||||
// view models | |||||
_unityContainer.RegisterType<CartViewModel>(); | |||||
_unityContainer.RegisterType<ProductsViewModel>(); | |||||
_unityContainer.RegisterType<LoginViewModel>(); | |||||
_unityContainer.RegisterType<MainViewModel>(); | |||||
_unityContainer.RegisterType<OrderDetailViewModel>(); | |||||
_unityContainer.RegisterType<OrdersViewModel>(); | |||||
_unityContainer.RegisterType<ProfileViewModel>(); | |||||
} | |||||
public T Resolve<T>() | |||||
{ | |||||
return _unityContainer.Resolve<T>(); | |||||
} | |||||
public object Resolve(Type type) | |||||
{ | |||||
return _unityContainer.Resolve(type); | |||||
} | |||||
public void Register<T>(T instance) | |||||
{ | |||||
_unityContainer.RegisterInstance<T>(instance); | |||||
} | |||||
public void Register<TInterface, T>() where T : TInterface | |||||
{ | |||||
_unityContainer.RegisterType<TInterface, T>(); | |||||
} | |||||
public void RegisterSingleton<TInterface, T>() where T : TInterface | |||||
{ | |||||
_unityContainer.RegisterType<TInterface, T>(new ContainerControlledLifetimeManager()); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,52 @@ | |||||
using eShopOnContainers.Core.Models.Orders; | |||||
using eShopOnContainers.Core.Services.Orders; | |||||
using eShopOnContainers.Core.ViewModels.Base; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class CartViewModel : ViewModelBase | |||||
{ | |||||
private int _badgeCount; | |||||
private Order _order; | |||||
private IOrdersService _orderService; | |||||
public CartViewModel(IOrdersService orderService) | |||||
{ | |||||
_orderService = orderService; | |||||
} | |||||
public int BadgeCount | |||||
{ | |||||
get { return _badgeCount; } | |||||
set | |||||
{ | |||||
_badgeCount = value; | |||||
RaisePropertyChanged(() => BadgeCount); | |||||
} | |||||
} | |||||
public Order Order | |||||
{ | |||||
get { return _order; } | |||||
set | |||||
{ | |||||
_order = value; | |||||
RaisePropertyChanged(() => Order); | |||||
} | |||||
} | |||||
public override async Task InitializeAsync(object navigationData) | |||||
{ | |||||
MessagingCenter.Subscribe<ProductsViewModel>(this, MessengerKeys.AddProduct, (sender) => | |||||
{ | |||||
BadgeCount++; | |||||
}); | |||||
Order = await _orderService.GetCartAsync(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,111 @@ | |||||
using eShopOnContainers.Core.Validations; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.Windows.Input; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class LoginViewModel : ViewModelBase | |||||
{ | |||||
private ValidatableObject<string> _userName; | |||||
private ValidatableObject<string> _password; | |||||
private bool _isValid; | |||||
public LoginViewModel() | |||||
{ | |||||
_userName = new ValidatableObject<string>(); | |||||
_password = new ValidatableObject<string>(); | |||||
AddValidations(); | |||||
} | |||||
public ValidatableObject<string> UserName | |||||
{ | |||||
get | |||||
{ | |||||
return _userName; | |||||
} | |||||
set | |||||
{ | |||||
_userName = value; | |||||
RaisePropertyChanged(() => UserName); | |||||
} | |||||
} | |||||
public ValidatableObject<string> Password | |||||
{ | |||||
get | |||||
{ | |||||
return _password; | |||||
} | |||||
set | |||||
{ | |||||
_password = value; | |||||
RaisePropertyChanged(() => Password); | |||||
} | |||||
} | |||||
public bool IsValid | |||||
{ | |||||
get | |||||
{ | |||||
return _isValid; | |||||
} | |||||
set | |||||
{ | |||||
_isValid = value; | |||||
RaisePropertyChanged(() => IsValid); | |||||
} | |||||
} | |||||
public ICommand SignInCommand => new Command(SignInAsync); | |||||
private async void SignInAsync() | |||||
{ | |||||
IsBusy = true; | |||||
IsValid = true; | |||||
bool isValid = Validate(); | |||||
bool isAuthenticated = false; | |||||
if (isValid) | |||||
{ | |||||
try | |||||
{ | |||||
isAuthenticated = true; | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Debug.WriteLine($"[SignIn] Error signing in: {ex}"); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
IsValid = false; | |||||
} | |||||
if (isAuthenticated) | |||||
{ | |||||
await NavigationService.NavigateToAsync<MainViewModel>(); | |||||
await NavigationService.RemoveLastFromBackStackAsync(); | |||||
} | |||||
IsBusy = false; | |||||
} | |||||
private bool Validate() | |||||
{ | |||||
bool isValidUser = _userName.Validate(); | |||||
bool isValidPassword = _password.Validate(); | |||||
return isValidUser && isValidPassword; | |||||
} | |||||
private void AddValidations() | |||||
{ | |||||
_userName.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "Username should not be empty" }); | |||||
_password.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "Password should not be empty" }); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class MainViewModel : ViewModelBase | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,8 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class OrderDetailViewModel : ViewModelBase | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,8 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class OrdersViewModel : ViewModelBase | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,45 @@ | |||||
using eShopOnContainers.Core.Models.Orders; | |||||
using eShopOnContainers.Core.Services.Orders; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using System.Collections.ObjectModel; | |||||
using System.Threading.Tasks; | |||||
using System.Windows.Input; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class ProfileViewModel : ViewModelBase | |||||
{ | |||||
private ObservableCollection<Order> _orders; | |||||
private IOrdersService _ordersService; | |||||
public ProfileViewModel(IOrdersService ordersService) | |||||
{ | |||||
_ordersService = ordersService; | |||||
} | |||||
public ObservableCollection<Order> Orders | |||||
{ | |||||
get { return _orders; } | |||||
set | |||||
{ | |||||
_orders = value; | |||||
RaisePropertyChanged(() => Orders); | |||||
} | |||||
} | |||||
public ICommand LogoutCommand => new Command(LogoutAsync); | |||||
public override async Task InitializeAsync(object navigationData) | |||||
{ | |||||
Orders = await _ordersService.GetOrdersAsync(); | |||||
} | |||||
private async void LogoutAsync() | |||||
{ | |||||
await NavigationService.NavigateToAsync<LoginViewModel>(); | |||||
await NavigationService.RemoveBackStackAsync(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,57 @@ | |||||
using System.Threading.Tasks; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using eShopOnContainers.Core.Services.Products; | |||||
using System.Collections.ObjectModel; | |||||
using eShopOnContainers.Core.Models.Products; | |||||
using Xamarin.Forms; | |||||
using eShopOnContainers.Core.ViewModels.Base; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class ProductsViewModel : ViewModelBase | |||||
{ | |||||
private ObservableCollection<Product> _products; | |||||
private Product _product; | |||||
private IProductsService _productsService; | |||||
public ProductsViewModel(IProductsService productsService) | |||||
{ | |||||
_productsService = productsService; | |||||
} | |||||
public ObservableCollection<Product> Products | |||||
{ | |||||
get { return _products; } | |||||
set | |||||
{ | |||||
_products = value; | |||||
RaisePropertyChanged(() => Products); | |||||
} | |||||
} | |||||
public Product Product | |||||
{ | |||||
get { return _product; } | |||||
set | |||||
{ | |||||
_product = value; | |||||
if (_product != null) | |||||
{ | |||||
AddProduct(); | |||||
} | |||||
} | |||||
} | |||||
public override async Task InitializeAsync(object navigationData) | |||||
{ | |||||
Products = await _productsService.GetProductsAsync(); | |||||
} | |||||
private void AddProduct() | |||||
{ | |||||
MessagingCenter.Send(this, MessengerKeys.AddProduct); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,139 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.CartView" | |||||
Title="Cart"> | |||||
<ContentPage.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="OrderTitleStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource MediumSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="Gray" /> | |||||
</Style> | |||||
<Style x:Key="OrderContentStyle" | |||||
TargetType="{x:Type Label}" | |||||
BasedOn="{StaticResource OrderTitleStyle}"> | |||||
<Setter Property="TextColor" | |||||
Value="Black" /> | |||||
</Style> | |||||
<Style x:Key="ShippingAddressStyle" | |||||
TargetType="{x:Type Label}" | |||||
BasedOn="{StaticResource OrderTitleStyle}"> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LargeSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="Black" /> | |||||
</Style> | |||||
<Style x:Key="AddressStyle" | |||||
TargetType="{x:Type Label}" | |||||
BasedOn="{StaticResource OrderTitleStyle}"> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LittleSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="Black" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentPage.Resources> | |||||
<ScrollView> | |||||
<Grid | |||||
BackgroundColor="{StaticResource BackgroundColor}"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
</Grid.RowDefinitions> | |||||
<!-- ORDER INFO --> | |||||
<Grid> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition /> | |||||
<ColumnDefinition /> | |||||
</Grid.ColumnDefinitions> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
</Grid.RowDefinitions> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Grid.Row="0" | |||||
Margin="12"> | |||||
<Label | |||||
Text="ORDER NUMBER" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Order.OrderNumber, Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Grid.Row="1" | |||||
Margin="12"> | |||||
<Label | |||||
Text="TOTAL" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Order.Total, StringFormat='${0:N}', Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="1" | |||||
Grid.Row="0" | |||||
Margin="12"> | |||||
<Label | |||||
Text="DATE" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Order.Date, Converter={StaticResource DatetimeConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="1" | |||||
Grid.Row="1" | |||||
Margin="12"> | |||||
<Label | |||||
Text="STATUS" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Order.Status, Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
</Grid> | |||||
<!-- SHIPPING ADDRESS --> | |||||
<Grid | |||||
Grid.Row="1" | |||||
Margin="12"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="*" /> | |||||
</Grid.RowDefinitions> | |||||
<Label | |||||
Grid.Row="0" | |||||
Text="SHIPPING ADDRESS" | |||||
Style="{StaticResource ShippingAddressStyle}"/> | |||||
<StackLayout | |||||
Grid.Row="1"> | |||||
<Label | |||||
Text="120 E 87th Street" | |||||
Style="{StaticResource AddressStyle}"/> | |||||
<Label | |||||
Text="Seattle, WA" | |||||
Style="{StaticResource AddressStyle}"/> | |||||
<Label | |||||
Text="98122" | |||||
Style="{StaticResource AddressStyle}"/> | |||||
<Label | |||||
Text="United States" | |||||
Style="{StaticResource AddressStyle}"/> | |||||
</StackLayout> | |||||
</Grid> | |||||
</Grid> | |||||
</ScrollView> | |||||
</ContentPage> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class CartView : ContentPage | |||||
{ | |||||
public CartView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<NavigationPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.CustomNavigationPage" | |||||
BackgroundColor="Transparent"> | |||||
</NavigationPage> |
@ -0,0 +1,17 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class CustomNavigationPage : NavigationPage | |||||
{ | |||||
public CustomNavigationPage() : base() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
public CustomNavigationPage(Page root) : base(root) | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,72 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<slideOverKit:SlideMenuView | |||||
xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
xmlns:slideOverKit="clr-namespace:SlideOverKit" | |||||
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core" | |||||
x:Class="eShopOnContainers.Core.Views.FiltersView" | |||||
MenuOrientations="TopToBottom" | |||||
BackgroundColor="{StaticResource BackgroundColor}" | |||||
HeightRequest="250" | |||||
IsFullScreen="True"> | |||||
<slideOverKit:SlideMenuView.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="FilterPickerStyle" | |||||
TargetType="{x:Type controls:BindablePicker}"> | |||||
<Setter Property="HeightRequest" | |||||
Value="48" /> | |||||
<Setter Property="BackgroundColor" | |||||
Value="Transparent" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Fill" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Fill" /> | |||||
</Style> | |||||
<Style x:Key="FilterButtonStyle" | |||||
TargetType="{x:Type Button}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="BackgroundColor" | |||||
Value="{StaticResource LightGreenColor}" /> | |||||
<Setter Property="HeightRequest" | |||||
Value="48" /> | |||||
<Setter Property="BorderRadius" | |||||
Value="0" /> | |||||
<Setter Property="BorderWidth" | |||||
Value="0" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Fill" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Fill" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</slideOverKit:SlideMenuView.Resources> | |||||
<Grid | |||||
Padding="0" | |||||
ColumnSpacing="0" | |||||
RowSpacing="0" | |||||
Margin="48, 24"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
</Grid.RowDefinitions> | |||||
<controls:BindablePicker | |||||
Grid.Row="0" | |||||
Title="BRAND" | |||||
Style="{StaticResource FilterPickerStyle}"/> | |||||
<controls:BindablePicker | |||||
Grid.Row="1" | |||||
Title="TYPE" | |||||
Style="{StaticResource FilterPickerStyle}"/> | |||||
<Button | |||||
Grid.Row="2" | |||||
Text="Apply" | |||||
Style="{StaticResource FilterButtonStyle}"/> | |||||
</Grid> | |||||
</slideOverKit:SlideMenuView> |
@ -0,0 +1,12 @@ | |||||
using SlideOverKit; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class FiltersView : SlideMenuView | |||||
{ | |||||
public FiltersView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,90 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.HomeView" | |||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core" | |||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core" | |||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core" | |||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core" | |||||
Title="Products"> | |||||
<ContentPage.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="ProductsListStyle" | |||||
TargetType="{x:Type ListView}"> | |||||
<Setter Property="RowHeight" | |||||
Value="400" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="0" /> | |||||
</Style> | |||||
<Style x:Key="FilterLabelStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
</Style> | |||||
<animations:StoryBoard | |||||
x:Key="ProductsAnimation" | |||||
Target="{x:Reference Products}"> | |||||
<animations:FadeInAnimation | |||||
Direction="Up" | |||||
Duration="1500" | |||||
Delay="250"/> | |||||
</animations:StoryBoard> | |||||
</ResourceDictionary> | |||||
</ContentPage.Resources> | |||||
<ContentPage.Triggers> | |||||
<EventTrigger | |||||
Event="Appearing"> | |||||
<triggers:BeginAnimation | |||||
Animation="{StaticResource ProductsAnimation}" /> | |||||
</EventTrigger> | |||||
</ContentPage.Triggers> | |||||
<Grid | |||||
ColumnSpacing="0" | |||||
RowSpacing="0"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="60" /> | |||||
<RowDefinition Height="*" /> | |||||
</Grid.RowDefinitions> | |||||
<!-- FILTERS --> | |||||
<Grid | |||||
BackgroundColor="{StaticResource LightGreenColor}"> | |||||
<Label | |||||
Text="FILTER" | |||||
Style="{StaticResource FilterLabelStyle}"/> | |||||
<Grid.GestureRecognizers> | |||||
<TapGestureRecognizer | |||||
Tapped="OnFilterChanged" | |||||
NumberOfTapsRequired="1" /> | |||||
</Grid.GestureRecognizers> | |||||
</Grid> | |||||
<!-- PRODUCTS --> | |||||
<ListView | |||||
x:Name="Products" | |||||
Grid.Row="1" | |||||
ItemsSource="{Binding Products}" | |||||
SelectedItem="{Binding Product, Mode=TwoWay}" | |||||
HasUnevenRows="True" | |||||
SeparatorVisibility="None" | |||||
CachingStrategy="RecycleElement" | |||||
Style="{StaticResource ProductsListStyle}"> | |||||
<ListView.ItemTemplate> | |||||
<DataTemplate> | |||||
<ViewCell> | |||||
<templates:ProductTemplate /> | |||||
</ViewCell> | |||||
</DataTemplate> | |||||
</ListView.ItemTemplate> | |||||
</ListView> | |||||
</Grid> | |||||
</ContentPage> |
@ -0,0 +1,46 @@ | |||||
using System; | |||||
using SlideOverKit; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class HomeView : ContentPage, IMenuContainerPage | |||||
{ | |||||
public HomeView() | |||||
{ | |||||
InitializeComponent(); | |||||
SlideMenu = new FiltersView(); | |||||
} | |||||
public Action HideMenuAction | |||||
{ | |||||
get; | |||||
set; | |||||
} | |||||
public Action ShowMenuAction | |||||
{ | |||||
get; | |||||
set; | |||||
} | |||||
public SlideMenuView SlideMenu | |||||
{ | |||||
get; | |||||
set; | |||||
} | |||||
private void OnFilterChanged(object sender, EventArgs e) | |||||
{ | |||||
if (SlideMenu.IsShown) | |||||
{ | |||||
HideMenuAction?.Invoke(); | |||||
} | |||||
else | |||||
{ | |||||
ShowMenuAction?.Invoke(); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,163 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.LoginView" | |||||
xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core" | |||||
xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core" | |||||
Title="eShop on Containers"> | |||||
<ContentPage.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="TitleLabelStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontAttributes" | |||||
Value="Bold" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource MediumSize}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="0, 12" /> | |||||
</Style> | |||||
<Style x:Key="HeaderLabelStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LittleSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource GreenColor}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Start" /> | |||||
</Style> | |||||
<Style x:Key="LoginButtonStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
</Style> | |||||
<animations:StoryBoard | |||||
x:Key="LoginAnimation" | |||||
Target="{x:Reference LoginPanel}"> | |||||
<animations:FadeInAnimation | |||||
Direction="Up" | |||||
Duration="1500" /> | |||||
</animations:StoryBoard> | |||||
</ResourceDictionary> | |||||
</ContentPage.Resources> | |||||
<ContentPage.Triggers> | |||||
<EventTrigger | |||||
Event="Appearing"> | |||||
<triggers:BeginAnimation | |||||
Animation="{StaticResource LoginAnimation}" /> | |||||
</EventTrigger> | |||||
</ContentPage.Triggers> | |||||
<Grid | |||||
BackgroundColor="{StaticResource BackgroundColor}"> | |||||
<Grid | |||||
x:Name="LoginPanel" | |||||
Padding="0" | |||||
ColumnSpacing="0" | |||||
RowSpacing="0"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="*" /> | |||||
<RowDefinition Height="60" /> | |||||
</Grid.RowDefinitions> | |||||
<!-- LOGIN / REGISTER --> | |||||
<Grid | |||||
Grid.Row="0" | |||||
Margin="48, 24"> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition /> | |||||
<ColumnDefinition /> | |||||
</Grid.ColumnDefinitions> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Orientation="Horizontal" | |||||
HorizontalOptions="Center"> | |||||
<Label | |||||
Text="[" | |||||
TextColor="{StaticResource LightGreenColor}"/> | |||||
<Label | |||||
Text="LOGIN" | |||||
FontAttributes="Bold"/> | |||||
<Label | |||||
Text="]" | |||||
TextColor="{StaticResource LightGreenColor}"/> | |||||
</StackLayout> | |||||
<Grid | |||||
Grid.Column="1" | |||||
HorizontalOptions="Center"> | |||||
<Label | |||||
Text="REGISTER" | |||||
TextColor="Gray"/> | |||||
</Grid> | |||||
</Grid> | |||||
<!-- INFO --> | |||||
<Label | |||||
Grid.Row="1" | |||||
Text="ARE YOU REGISTERED?" | |||||
Style="{StaticResource TitleLabelStyle}"/> | |||||
<!-- LOGIN FORM --> | |||||
<StackLayout | |||||
Grid.Row="2" | |||||
Margin="24"> | |||||
<Label | |||||
Text="User name or email" | |||||
Style="{StaticResource HeaderLabelStyle}"/> | |||||
<Entry | |||||
Text="{Binding UserName.Value, Mode=TwoWay}"/> | |||||
<Label | |||||
Text="Password" | |||||
Style="{StaticResource HeaderLabelStyle}"/> | |||||
<Entry | |||||
IsPassword="True" | |||||
Text="{Binding Password.Value, Mode=TwoWay}" /> | |||||
</StackLayout> | |||||
<!-- LOGIN BUTTON --> | |||||
<Grid | |||||
BackgroundColor="{StaticResource LightGreenColor}" | |||||
Grid.Row="3" | |||||
Padding="0" | |||||
ColumnSpacing="0" | |||||
RowSpacing="0"> | |||||
<Label | |||||
Text="[ LOGIN ]" | |||||
Style="{StaticResource LoginButtonStyle}"/> | |||||
<Grid.GestureRecognizers> | |||||
<TapGestureRecognizer | |||||
Command="{Binding SignInCommand}" | |||||
NumberOfTapsRequired="1" /> | |||||
</Grid.GestureRecognizers> | |||||
</Grid> | |||||
</Grid> | |||||
<!-- INDICATOR --> | |||||
<ActivityIndicator | |||||
Color="{StaticResource AccentColor}" | |||||
IsRunning="{Binding IsBusy}" | |||||
IsVisible="{Binding IsBusy}" | |||||
VerticalOptions="Center" | |||||
HorizontalOptions="Center"> | |||||
<ActivityIndicator.WidthRequest> | |||||
<OnPlatform | |||||
x:TypeArguments="x:Double" | |||||
iOS="100" | |||||
Android="100" | |||||
WinPhone="400" /> | |||||
</ActivityIndicator.WidthRequest> | |||||
</ActivityIndicator> | |||||
</Grid> | |||||
</ContentPage> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class LoginView : ContentPage | |||||
{ | |||||
public LoginView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,42 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.MainView" | |||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core" | |||||
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core" | |||||
BarBackgroundColor="{StaticResource DarkGreenColor}" | |||||
BackgroundColor="{StaticResource BackgroundColor}" | |||||
Title="eShop on Containers"> | |||||
<views:HomeView | |||||
x:Name="HomeView"> | |||||
<views:HomeView.Icon> | |||||
<OnPlatform | |||||
x:TypeArguments="FileImageSource" | |||||
Android="menu_filter" | |||||
iOS="menu_filter" | |||||
WinPhone="Assets\menu_filter.png"/> | |||||
</views:HomeView.Icon> | |||||
</views:HomeView> | |||||
<views:ProfileView | |||||
x:Name="ProfileView"> | |||||
<views:HomeView.Icon> | |||||
<OnPlatform | |||||
x:TypeArguments="FileImageSource" | |||||
Android="menu_profile" | |||||
iOS="menu_profile" | |||||
WinPhone="Assets\menu_profile.png"/> | |||||
</views:HomeView.Icon> | |||||
</views:ProfileView> | |||||
<views:CartView | |||||
x:Name="CartView" | |||||
controls:CustomTabbedPage.BadgeText="{Binding BadgeCount}" | |||||
controls:CustomTabbedPage.BadgeColor="{StaticResource LightGreenColor}"> | |||||
<views:HomeView.Icon> | |||||
<OnPlatform | |||||
x:TypeArguments="FileImageSource" | |||||
Android="menu_cart" | |||||
iOS="menu_cart" | |||||
WinPhone="Assets\menu_cart.png"/> | |||||
</views:HomeView.Icon> | |||||
</views:CartView> | |||||
</TabbedPage> |
@ -0,0 +1,31 @@ | |||||
using eShopOnContainers.Core.ViewModels; | |||||
using eShopOnContainers.ViewModels.Base; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class MainView : TabbedPage | |||||
{ | |||||
public MainView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
protected override async void OnAppearing() | |||||
{ | |||||
base.OnAppearing(); | |||||
var homeViewModel = ViewModelLocator.Instance.Resolve<ProductsViewModel>(); | |||||
await homeViewModel.InitializeAsync(null); | |||||
HomeView.BindingContext = homeViewModel; | |||||
var profileViewModel = ViewModelLocator.Instance.Resolve<ProfileViewModel>(); | |||||
await profileViewModel.InitializeAsync(null); | |||||
ProfileView.BindingContext = profileViewModel; | |||||
var cartViewModel = ViewModelLocator.Instance.Resolve<CartViewModel>(); | |||||
await cartViewModel.InitializeAsync(null); | |||||
CartView.BindingContext = cartViewModel; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.OrderDetailView"> | |||||
</ContentPage> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class OrderDetailView : ContentPage | |||||
{ | |||||
public OrderDetailView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.OrdersView"> | |||||
</ContentPage> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class OrdersView : ContentPage | |||||
{ | |||||
public OrdersView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,96 @@ | |||||
<?xml version="1.0" encoding="utf-8" ?> | |||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.ProfileView" | |||||
xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core" | |||||
xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core" | |||||
Title="My profile"> | |||||
<ContentPage.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="LogoutLabelStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
</Style> | |||||
<Style x:Key="LoginButtonStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource WhiteColor}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
</Style> | |||||
<Style x:Key="MyOrdersLabelStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource MediumSize}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="0, 12" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentPage.Resources> | |||||
<Grid | |||||
Padding="0" | |||||
ColumnSpacing="0" | |||||
RowSpacing="0" | |||||
BackgroundColor="{StaticResource BackgroundColor}"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="60" /> | |||||
<RowDefinition Height="*" /> | |||||
</Grid.RowDefinitions> | |||||
<!-- LOG OUT BUTTON --> | |||||
<Grid | |||||
Grid.Row="0" | |||||
BackgroundColor="{StaticResource GrayColor}"> | |||||
<Label | |||||
Text="LOG OUT" | |||||
Style="{StaticResource LogoutLabelStyle}"/> | |||||
<Grid.GestureRecognizers> | |||||
<TapGestureRecognizer | |||||
Command="{Binding LogoutCommand}" | |||||
NumberOfTapsRequired="1" /> | |||||
</Grid.GestureRecognizers> | |||||
</Grid> | |||||
<!-- ORDERS --> | |||||
<Grid | |||||
Grid.Row="1"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="*" /> | |||||
</Grid.RowDefinitions> | |||||
<Label | |||||
Grid.Row="0" | |||||
Text="MY ORDERS" | |||||
Style="{StaticResource MyOrdersLabelStyle}"/> | |||||
<ListView | |||||
Grid.Row="1" | |||||
ItemsSource="{Binding Orders}" | |||||
HasUnevenRows="True" | |||||
SeparatorVisibility="None" | |||||
CachingStrategy="RecycleElement"> | |||||
<ListView.ItemTemplate> | |||||
<DataTemplate> | |||||
<ViewCell> | |||||
<templates:OrderTemplate /> | |||||
</ViewCell> | |||||
</DataTemplate> | |||||
</ListView.ItemTemplate> | |||||
</ListView> | |||||
</Grid> | |||||
</Grid> | |||||
</ContentPage> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class ProfileView : ContentPage | |||||
{ | |||||
public ProfileView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,91 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<ContentView | |||||
xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.Templates.OrderTemplate"> | |||||
<ContentView.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="OrderTitleStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource MediumSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="Gray" /> | |||||
</Style> | |||||
<Style x:Key="OrderContentStyle" | |||||
TargetType="{x:Type Label}" | |||||
BasedOn="{StaticResource OrderTitleStyle}"> | |||||
<Setter Property="TextColor" | |||||
Value="Black" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentView.Resources> | |||||
<ContentView.Content> | |||||
<Grid | |||||
BackgroundColor="{StaticResource BackgroundColor}"> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition /> | |||||
<ColumnDefinition /> | |||||
</Grid.ColumnDefinitions> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition /> | |||||
<RowDefinition /> | |||||
<RowDefinition Height="1" /> | |||||
</Grid.RowDefinitions> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Grid.Row="0" | |||||
Margin="12"> | |||||
<Label | |||||
Text="ORDER NUMBER" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding OrderNumber, Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Grid.Row="1" | |||||
Margin="12"> | |||||
<Label | |||||
Text="TOTAL" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Total, StringFormat='${0:N}', Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="1" | |||||
Grid.Row="0" | |||||
Margin="12"> | |||||
<Label | |||||
Text="DATE" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Date, Converter={StaticResource DatetimeConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<StackLayout | |||||
Grid.Column="1" | |||||
Grid.Row="1" | |||||
Margin="12"> | |||||
<Label | |||||
Text="STATUS" | |||||
Style="{StaticResource OrderTitleStyle}"/> | |||||
<Label | |||||
Text="{Binding Status, Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource OrderContentStyle}"/> | |||||
</StackLayout> | |||||
<Grid | |||||
Grid.Column="0" | |||||
Grid.ColumnSpan="2" | |||||
Grid.Row="2" | |||||
BackgroundColor="Gray"/> | |||||
</Grid> | |||||
</ContentView.Content> | |||||
</ContentView> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views.Templates | |||||
{ | |||||
public partial class OrderTemplate : ContentView | |||||
{ | |||||
public OrderTemplate() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,111 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<ContentView | |||||
xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Views.Templates.ProductTemplate"> | |||||
<ContentView.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="ProductNameStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LargeSize}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="0, 12, 0, 6" /> | |||||
</Style> | |||||
<Style x:Key="ProductPriceStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontAttributes" | |||||
Value="Bold" /> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource BigSize}" /> | |||||
<Setter Property="TextColor" | |||||
Value="{StaticResource BlackColor}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="0, 6, 0, 12" /> | |||||
</Style> | |||||
<Style x:Key="AddButtonStyle" | |||||
TargetType="{x:Type Grid}"> | |||||
<Setter Property="HeightRequest" | |||||
Value="42" /> | |||||
<Setter Property="WidthRequest" | |||||
Value="42" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="End" /> | |||||
<Setter Property="Margin" | |||||
Value="0,0,0,24" /> | |||||
</Style> | |||||
<Style x:Key="AddImageStyle" | |||||
TargetType="{x:Type Image}"> | |||||
<Setter Property="HeightRequest" | |||||
Value="24" /> | |||||
<Setter Property="WidthRequest" | |||||
Value="24" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentView.Resources> | |||||
<ContentView.Content> | |||||
<Grid | |||||
BackgroundColor="{StaticResource BackgroundColor}" | |||||
Padding="0" | |||||
Margin="0"> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="250" /> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="Auto" /> | |||||
</Grid.RowDefinitions> | |||||
<Image | |||||
Grid.Row="0" | |||||
Source="{Binding Image}" | |||||
Aspect="AspectFill"/> | |||||
<Grid | |||||
Grid.Row="0" | |||||
Grid.RowSpan="2" | |||||
Style="{StaticResource AddButtonStyle}"> | |||||
<BoxView | |||||
BackgroundColor="{StaticResource LightGreenColor}" | |||||
StyleClass="Circle"/> | |||||
<Image | |||||
Aspect="AspectFit" | |||||
Style="{StaticResource AddImageStyle}"> | |||||
<Image.Margin> | |||||
<OnPlatform | |||||
x:TypeArguments="Thickness" | |||||
Android="6, 12, 12, 12" | |||||
iOS="6, 12, 12, 12" | |||||
WinPhone="8, 12, 12, 12"/> | |||||
</Image.Margin> | |||||
<Image.Source> | |||||
<OnPlatform | |||||
x:TypeArguments="ImageSource" | |||||
Android="product_add" | |||||
iOS="product_add" | |||||
WinPhone="Assets\product_add.png"/> | |||||
</Image.Source> | |||||
</Image> | |||||
</Grid> | |||||
<Label | |||||
Grid.Row="1" | |||||
Text="{Binding Name, Converter={StaticResource ToUpperConverter}}" | |||||
Style="{StaticResource ProductNameStyle}"/> | |||||
<Label | |||||
Grid.Row="2" | |||||
Text="{Binding Price, StringFormat='${0:N}'}" | |||||
Style="{StaticResource ProductPriceStyle}"/> | |||||
</Grid> | |||||
</ContentView.Content> | |||||
</ContentView> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views.Templates | |||||
{ | |||||
public partial class ProductTemplate : ContentView | |||||
{ | |||||
public ProductTemplate() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,11 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<configuration> | |||||
<runtime> | |||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |||||
<dependentAssembly> | |||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> | |||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" /> | |||||
</dependentAssembly> | |||||
</assemblyBinding> | |||||
</runtime> | |||||
</configuration> |
@ -0,0 +1,258 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||||
<PropertyGroup> | |||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> | |||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||||
<ProjectGuid>{65116D1C-145B-4693-ABDA-F0FB6F425191}</ProjectGuid> | |||||
<OutputType>Library</OutputType> | |||||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||||
<RootNamespace>eShopOnContainers.Core</RootNamespace> | |||||
<AssemblyName>eShopOnContainers.Core</AssemblyName> | |||||
<FileAlignment>512</FileAlignment> | |||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |||||
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile> | |||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||||
<NuGetPackageImportStamp> | |||||
</NuGetPackageImportStamp> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||||
<DebugSymbols>true</DebugSymbols> | |||||
<DebugType>full</DebugType> | |||||
<Optimize>false</Optimize> | |||||
<OutputPath>bin\Debug\</OutputPath> | |||||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
<ErrorReport>prompt</ErrorReport> | |||||
<WarningLevel>4</WarningLevel> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||||
<DebugType>pdbonly</DebugType> | |||||
<Optimize>true</Optimize> | |||||
<OutputPath>bin\Release\</OutputPath> | |||||
<DefineConstants>TRACE</DefineConstants> | |||||
<ErrorReport>prompt</ErrorReport> | |||||
<WarningLevel>4</WarningLevel> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<Compile Include="Animations\Base\AnimationBase.cs" /> | |||||
<Compile Include="Animations\Base\EasingType.cs" /> | |||||
<Compile Include="Animations\FadeToAnimation.cs" /> | |||||
<Compile Include="Animations\StoryBoard.cs" /> | |||||
<Compile Include="App.xaml.cs"> | |||||
<DependentUpon>App.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Controls\BindablePicker.cs" /> | |||||
<Compile Include="Controls\CustomTabbedPage.cs" /> | |||||
<Compile Include="Converters\DatetimeConverter.cs" /> | |||||
<Compile Include="Converters\ToUpperConverter.cs" /> | |||||
<Compile Include="Effects\LineColorEffect.cs" /> | |||||
<Compile Include="Extensions\AnimationExtension.cs" /> | |||||
<Compile Include="Helpers\EasingHelper.cs" /> | |||||
<Compile Include="Models\Orders\Order.cs" /> | |||||
<Compile Include="Models\Orders\OrderStatus.cs" /> | |||||
<Compile Include="Models\Products\Product.cs" /> | |||||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||||
<Compile Include="Services\Dialog\DialogService.cs" /> | |||||
<Compile Include="Services\Dialog\IDialogService.cs" /> | |||||
<Compile Include="Services\Navigation\INavigationService.cs" /> | |||||
<Compile Include="Services\Navigation\NavigationService.cs" /> | |||||
<Compile Include="Services\Orders\FakeOrdersService.cs" /> | |||||
<Compile Include="Services\Orders\IOrdersService.cs" /> | |||||
<Compile Include="Services\Products\FakeProductsService.cs" /> | |||||
<Compile Include="Services\Products\IProductsService.cs" /> | |||||
<Compile Include="Triggers\BeginAnimation.cs" /> | |||||
<Compile Include="Validations\IsNotNullOrEmptyRule.cs" /> | |||||
<Compile Include="Validations\IValidationRule.cs" /> | |||||
<Compile Include="Validations\IValidity.cs" /> | |||||
<Compile Include="Validations\ValidatableObject.cs" /> | |||||
<Compile Include="ViewModels\Base\ExtendedBindableObject.cs" /> | |||||
<Compile Include="ViewModels\Base\MessengerKeys.cs" /> | |||||
<Compile Include="ViewModels\Base\ViewModelBase.cs" /> | |||||
<Compile Include="ViewModels\Base\ViewModelLocator.cs" /> | |||||
<Compile Include="ViewModels\CartViewModel.cs" /> | |||||
<Compile Include="ViewModels\ProductsViewModel.cs" /> | |||||
<Compile Include="ViewModels\LoginViewModel.cs" /> | |||||
<Compile Include="ViewModels\MainViewModel.cs" /> | |||||
<Compile Include="ViewModels\OrderDetailViewModel.cs" /> | |||||
<Compile Include="ViewModels\OrdersViewModel.cs" /> | |||||
<Compile Include="ViewModels\ProfileViewModel.cs" /> | |||||
<Compile Include="Views\CartView.xaml.cs"> | |||||
<DependentUpon>CartView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\CustomNavigationPage.xaml.cs"> | |||||
<DependentUpon>CustomNavigationPage.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\FiltersView.xaml.cs"> | |||||
<DependentUpon>FiltersView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\HomeView.xaml.cs"> | |||||
<DependentUpon>HomeView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\LoginView.xaml.cs"> | |||||
<DependentUpon>LoginView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\MainView.xaml.cs"> | |||||
<DependentUpon>MainView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\OrderDetailView.xaml.cs"> | |||||
<DependentUpon>OrderDetailView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\OrdersView.xaml.cs"> | |||||
<DependentUpon>OrdersView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\ProfileView.xaml.cs"> | |||||
<DependentUpon>ProfileView.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\Templates\OrderTemplate.xaml.cs"> | |||||
<DependentUpon>OrderTemplate.xaml</DependentUpon> | |||||
</Compile> | |||||
<Compile Include="Views\Templates\ProductTemplate.xaml.cs"> | |||||
<DependentUpon>ProductTemplate.xaml</DependentUpon> | |||||
</Compile> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="App.xaml"> | |||||
<SubType>Designer</SubType> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\FiltersView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<Reference Include="Acr.UserDialogs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Acr.UserDialogs.6.3.1\lib\portable-win+net45+wp8+win8+wpa81\Acr.UserDialogs.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Acr.UserDialogs.Interface, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Acr.UserDialogs.6.3.1\lib\portable-win+net45+wp8+win8+wpa81\Acr.UserDialogs.Interface.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Microsoft.Practices.Unity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Unity.4.0.1\lib\portable-net45+wp80+win8+wpa81+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="ModernHttpClient, Version=2.4.2.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\modernhttpclient.2.4.2\lib\Portable-Net45+WinRT45+WP8+WPA81\ModernHttpClient.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="SlideOverKit, Version=1.0.6135.18790, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\SlideOverKit.2.1.4\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SlideOverKit.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.2.3.2.127\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Pages, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.Pages.2.3.0.38-pre2\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Pages.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.2.3.2.127\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Platform.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Theme.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.Theme.Base.1.0.0.43-pre1\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Theme.Base.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Theme.Light, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.Theme.Light.1.0.0.43-pre1\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Theme.Light.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Xamarin.Forms.Xaml, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>..\..\packages\Xamarin.Forms.2.3.2.127\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Xaml.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="app.config" /> | |||||
<None Include="packages.config" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\HomeView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\CartView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\LoginView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\ProfileView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\OrderDetailView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\OrdersView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\CustomNavigationPage.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\Templates\ProductTemplate.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\MainView.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<EmbeddedResource Include="Views\Templates\OrderTemplate.xaml"> | |||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> | |||||
<SubType>Designer</SubType> | |||||
</EmbeddedResource> | |||||
</ItemGroup> | |||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> | |||||
<Import Project="..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" /> | |||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||||
<PropertyGroup> | |||||
<ErrorText>Este proyecto hace referencia a los paquetes NuGet que faltan en este equipo. Use la restauración de paquetes NuGet para descargarlos. Para obtener más información, consulte http://go.microsoft.com/fwlink/?LinkID=322105. El archivo que falta es {0}.</ErrorText> | |||||
</PropertyGroup> | |||||
<Error Condition="!Exists('..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets'))" /> | |||||
<Error Condition="!Exists('..\..\packages\StyleCop.MSBuild.5.0.0-alpha01\build\StyleCop.MSBuild.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\StyleCop.MSBuild.5.0.0-alpha01\build\StyleCop.MSBuild.targets'))" /> | |||||
</Target> | |||||
<Import Project="..\..\packages\StyleCop.MSBuild.5.0.0-alpha01\build\StyleCop.MSBuild.targets" Condition="Exists('..\..\packages\StyleCop.MSBuild.5.0.0-alpha01\build\StyleCop.MSBuild.targets')" /> | |||||
</Project> |
@ -0,0 +1,15 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<packages> | |||||
<package id="Acr.UserDialogs" version="6.3.1" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="CommonServiceLocator" version="1.3" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="modernhttpclient" version="2.4.2" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="SlideOverKit" version="2.1.4" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Splat" version="1.6.2" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="StyleCop.MSBuild" version="5.0.0-alpha01" targetFramework="portable45-net45+win8+wp8+wpa81" developmentDependency="true" /> | |||||
<package id="Unity" version="4.0.1" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Xamarin.Forms" version="2.3.2.127" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Xamarin.Forms.Pages" version="2.3.0.38-pre2" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Xamarin.Forms.Theme.Base" version="1.0.0.43-pre1" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
<package id="Xamarin.Forms.Theme.Light" version="1.0.0.43-pre1" targetFramework="portable45-net45+win8+wp8+wpa81" /> | |||||
</packages> |
@ -0,0 +1,37 @@ | |||||
using Android.App; | |||||
using Android.OS; | |||||
using Android.Content.PM; | |||||
using Android.Views; | |||||
namespace eShopOnContainers.Droid.Activities | |||||
{ | |||||
[Activity( | |||||
Label = "eShopOnContainers", | |||||
Icon = "@drawable/icon", | |||||
Theme = "@style/MainTheme", | |||||
MainLauncher = true, | |||||
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] | |||||
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity | |||||
{ | |||||
protected override void OnCreate(Bundle bundle) | |||||
{ | |||||
TabLayoutResource = Resource.Layout.Tabbar; | |||||
ToolbarResource = Resource.Layout.Toolbar; | |||||
base.OnCreate(bundle); | |||||
global::Xamarin.Forms.Forms.Init(this, bundle); | |||||
LoadApplication(new App()); | |||||
var x = typeof(Xamarin.Forms.Themes.LightThemeResources); | |||||
x = typeof(Xamarin.Forms.Themes.Android.UnderlineEffect); | |||||
Window window = this.Window; | |||||
window.ClearFlags(WindowManagerFlags.TranslucentStatus); | |||||
window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds); | |||||
window.SetStatusBarColor(Android.Graphics.Color.Rgb(0, 166, 156)); | |||||
} | |||||
} | |||||
} | |||||
@ -0,0 +1,31 @@ | |||||
using Android.App; | |||||
using Android.Content; | |||||
using Android.Content.PM; | |||||
using Android.OS; | |||||
using Android.Support.V7.App; | |||||
namespace eShopOnContainers.Droid.Activities | |||||
{ | |||||
[Activity( | |||||
Label = "eShopOnContainers", | |||||
Icon = "@drawable/icon", | |||||
Theme = "@style/Theme.Splash", | |||||
MainLauncher = true, | |||||
NoHistory = true, | |||||
ScreenOrientation = ScreenOrientation.Portrait)] | |||||
public class SplashActivity : AppCompatActivity | |||||
{ | |||||
protected override void OnCreate(Bundle bundle) | |||||
{ | |||||
base.OnCreate(bundle); | |||||
InvokeMainActivity(); | |||||
} | |||||
private void InvokeMainActivity() | |||||
{ | |||||
var mainActivityIntent = new Intent(this, typeof(MainActivity)); | |||||
StartActivity(mainActivityIntent); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
Any raw assets you want to be deployed with your application can be placed in | |||||
this directory (and child directories) and given a Build Action of "AndroidAsset". | |||||
These files will be deployed with you package and will be accessible using Android's | |||||
AssetManager, like this: | |||||
public class ReadAsset : Activity | |||||
{ | |||||
protected override void OnCreate (Bundle bundle) | |||||
{ | |||||
base.OnCreate (bundle); | |||||
InputStream input = Assets.Open ("my_asset.txt"); | |||||
} | |||||
} | |||||
Additionally, some Android functions will automatically load asset files: | |||||
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); |
@ -0,0 +1,58 @@ | |||||
using Xamarin.Forms; | |||||
using eShopOnContainers.Droid.Effects; | |||||
using Xamarin.Forms.Platform.Android; | |||||
using System; | |||||
using Android.Widget; | |||||
using eShopOnContainers.Core.Effects; | |||||
using System.ComponentModel; | |||||
using System.Diagnostics; | |||||
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")] | |||||
namespace eShopOnContainers.Droid.Effects | |||||
{ | |||||
public class EntryLineColorEffect : PlatformEffect | |||||
{ | |||||
EditText control; | |||||
protected override void OnAttached() | |||||
{ | |||||
try | |||||
{ | |||||
control = Control as EditText; | |||||
UpdateLineColor(); | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); | |||||
} | |||||
} | |||||
protected override void OnDetached() | |||||
{ | |||||
control = null; | |||||
} | |||||
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) | |||||
{ | |||||
if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName) | |||||
{ | |||||
UpdateLineColor(); | |||||
} | |||||
} | |||||
private void UpdateLineColor() | |||||
{ | |||||
try | |||||
{ | |||||
if (control != null) | |||||
{ | |||||
control.Background.SetColorFilter(LineColorEffect.GetLineColor(Element).ToAndroid(), Android.Graphics.PorterDuff.Mode.SrcAtop); | |||||
} | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Debug.WriteLine(ex.Message); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,38 @@ | |||||
using Android.Views; | |||||
namespace eShopOnContainers.Droid.Extensions | |||||
{ | |||||
internal static class ViewExtensions | |||||
{ | |||||
public static T FindChildOfType<T>(this ViewGroup parent) where T : View | |||||
{ | |||||
if (parent == null) | |||||
return null; | |||||
if (parent.ChildCount == 0) | |||||
return null; | |||||
for (var i = 0; i < parent.ChildCount; i++) | |||||
{ | |||||
var child = parent.GetChildAt(i); | |||||
var typedChild = child as T; | |||||
if (typedChild != null) | |||||
{ | |||||
return typedChild; | |||||
} | |||||
if (!(child is ViewGroup)) | |||||
continue; | |||||
var result = FindChildOfType<T>(child as ViewGroup); | |||||
if (result != null) | |||||
return result; | |||||
} | |||||
return null; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,5 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |||||
<uses-sdk android:minSdkVersion="15" /> | |||||
<application android:label="eShopOnContainers.Droid"></application> | |||||
</manifest> |
@ -0,0 +1,34 @@ | |||||
using System.Reflection; | |||||
using System.Runtime.CompilerServices; | |||||
using System.Runtime.InteropServices; | |||||
using Android.App; | |||||
// General Information about an assembly is controlled through the following | |||||
// set of attributes. Change these attribute values to modify the information | |||||
// associated with an assembly. | |||||
[assembly: AssemblyTitle("eShopOnContainers.Droid")] | |||||
[assembly: AssemblyDescription("")] | |||||
[assembly: AssemblyConfiguration("")] | |||||
[assembly: AssemblyCompany("")] | |||||
[assembly: AssemblyProduct("eShopOnContainers.Droid")] | |||||
[assembly: AssemblyCopyright("Copyright © 2014")] | |||||
[assembly: AssemblyTrademark("")] | |||||
[assembly: AssemblyCulture("")] | |||||
[assembly: ComVisible(false)] | |||||
// Version information for an assembly consists of the following four values: | |||||
// | |||||
// Major Version | |||||
// Minor Version | |||||
// Build Number | |||||
// Revision | |||||
// | |||||
// You can specify all the values or you can default the Build and Revision Numbers | |||||
// by using the '*' as shown below: | |||||
// [assembly: AssemblyVersion("1.0.*")] | |||||
[assembly: AssemblyVersion("1.0.0.0")] | |||||
[assembly: AssemblyFileVersion("1.0.0.0")] | |||||
// Add some common permissions, these can be removed if not needed | |||||
[assembly: UsesPermission(Android.Manifest.Permission.Internet)] | |||||
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] |
@ -0,0 +1,240 @@ | |||||
using System; | |||||
using Android.Content; | |||||
using Android.Views; | |||||
using Android.Widget; | |||||
using Android.Graphics.Drawables; | |||||
using Android.Views.Animations; | |||||
using Android.Graphics.Drawables.Shapes; | |||||
using Android.Util; | |||||
using Android.Graphics; | |||||
namespace eShopOnContainers.Droid.Renderers | |||||
{ | |||||
public class BadgeView : TextView | |||||
{ | |||||
public enum BadgePosition | |||||
{ | |||||
PositionTopLeft = 1, | |||||
PositionTopRight = 2, | |||||
PositionBottomLeft = 3, | |||||
PositionBottomRight = 4, | |||||
PositionCenter = 5 | |||||
} | |||||
private const int DefaultHmarginDip = -10; | |||||
private const int DefaultVmarginDip = -5; | |||||
private const int DefaultLrPaddingDip = 4; | |||||
private const int DefaultCornerRadiusDip = 7; | |||||
private static Animation _fadeInAnimation; | |||||
private static Animation _fadeOutAnimation; | |||||
private Context _context; | |||||
private readonly Color _defaultBadgeColor = Color.ParseColor("#CCFF0000"); | |||||
private ShapeDrawable _backgroundShape; | |||||
public View Target { get; private set; } | |||||
public BadgePosition Postion { get; set; } = BadgePosition.PositionTopRight; | |||||
public int BadgeMarginH { get; set; } | |||||
public int BadgeMarginV { get; set; } | |||||
public static int TextSizeDip { get; set; } = 11; | |||||
public Color BadgeColor | |||||
{ | |||||
get { return _backgroundShape.Paint.Color; } | |||||
set | |||||
{ | |||||
_backgroundShape.Paint.Color = value; | |||||
Background.InvalidateSelf(); | |||||
} | |||||
} | |||||
public Color TextColor | |||||
{ | |||||
get { return new Color(CurrentTextColor); } | |||||
set { SetTextColor(value); } | |||||
} | |||||
public BadgeView(Context context, View target) : this(context, null, Android.Resource.Attribute.TextViewStyle, target) | |||||
{ | |||||
} | |||||
public BadgeView(Context context, IAttributeSet attrs, int defStyle, View target) : base(context, attrs, defStyle) | |||||
{ | |||||
Init(context, target); | |||||
} | |||||
private void Init(Context context, View target) | |||||
{ | |||||
_context = context; | |||||
Target = target; | |||||
BadgeMarginH = DipToPixels(DefaultHmarginDip); | |||||
BadgeMarginV = DipToPixels(DefaultVmarginDip); | |||||
Typeface = Typeface.DefaultBold; | |||||
var paddingPixels = DipToPixels(DefaultLrPaddingDip); | |||||
SetPadding(paddingPixels, 0, paddingPixels, 0); | |||||
SetTextColor(Color.White); | |||||
SetTextSize(ComplexUnitType.Dip, TextSizeDip); | |||||
_fadeInAnimation = new AlphaAnimation(0, 1) | |||||
{ | |||||
Interpolator = new DecelerateInterpolator(), | |||||
Duration = 200 | |||||
}; | |||||
_fadeOutAnimation = new AlphaAnimation(1, 0) | |||||
{ | |||||
Interpolator = new AccelerateInterpolator(), | |||||
Duration = 200 | |||||
}; | |||||
_backgroundShape = CreateBackgroundShape(); | |||||
Background = _backgroundShape; | |||||
BadgeColor = _defaultBadgeColor; | |||||
if (Target != null) | |||||
{ | |||||
ApplyTo(Target); | |||||
} | |||||
else | |||||
{ | |||||
Show(); | |||||
} | |||||
} | |||||
private ShapeDrawable CreateBackgroundShape() | |||||
{ | |||||
var radius = DipToPixels(DefaultCornerRadiusDip); | |||||
var outerR = new float[] { radius, radius, radius, radius, radius, radius, radius, radius }; | |||||
return new ShapeDrawable(new RoundRectShape(outerR, null, null)); | |||||
} | |||||
private void ApplyTo(View target) | |||||
{ | |||||
var lp = target.LayoutParameters; | |||||
var parent = target.Parent; | |||||
var group = parent as ViewGroup; | |||||
if (group == null) | |||||
{ | |||||
Console.WriteLine("Badge target parent has to be a view group"); | |||||
return; | |||||
} | |||||
group.SetClipChildren(false); | |||||
group.SetClipToPadding(false); | |||||
var container = new FrameLayout(_context); | |||||
var index = group.IndexOfChild(target); | |||||
group.RemoveView(target); | |||||
group.AddView(container, index, lp); | |||||
container.AddView(target); | |||||
group.Invalidate(); | |||||
Visibility = ViewStates.Gone; | |||||
container.AddView(this); | |||||
} | |||||
public void Show() | |||||
{ | |||||
Show(false, null); | |||||
} | |||||
public void Show(bool animate) | |||||
{ | |||||
Show(animate, _fadeInAnimation); | |||||
} | |||||
public void Hide(bool animate) | |||||
{ | |||||
Hide(animate, _fadeOutAnimation); | |||||
} | |||||
private void Show(bool animate, Animation anim) | |||||
{ | |||||
ApplyLayoutParams(); | |||||
if (animate) | |||||
{ | |||||
StartAnimation(anim); | |||||
} | |||||
Visibility = ViewStates.Visible; | |||||
} | |||||
private void Hide(bool animate, Animation anim) | |||||
{ | |||||
Visibility = ViewStates.Gone; | |||||
if (animate) | |||||
{ | |||||
StartAnimation(anim); | |||||
} | |||||
} | |||||
private void ApplyLayoutParams() | |||||
{ | |||||
var layoutParameters = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); | |||||
switch (Postion) | |||||
{ | |||||
case BadgePosition.PositionTopLeft: | |||||
layoutParameters.Gravity = GravityFlags.Left | GravityFlags.Top; | |||||
layoutParameters.SetMargins(BadgeMarginH, BadgeMarginV, 0, 0); | |||||
break; | |||||
case BadgePosition.PositionTopRight: | |||||
layoutParameters.Gravity = GravityFlags.Right | GravityFlags.Top; | |||||
layoutParameters.SetMargins(0, BadgeMarginV, BadgeMarginH, 0); | |||||
break; | |||||
case BadgePosition.PositionBottomLeft: | |||||
layoutParameters.Gravity = GravityFlags.Left | GravityFlags.Bottom; | |||||
layoutParameters.SetMargins(BadgeMarginH, 0, 0, BadgeMarginV); | |||||
break; | |||||
case BadgePosition.PositionBottomRight: | |||||
layoutParameters.Gravity = GravityFlags.Right | GravityFlags.Bottom; | |||||
layoutParameters.SetMargins(0, 0, BadgeMarginH, BadgeMarginV); | |||||
break; | |||||
case BadgePosition.PositionCenter: | |||||
layoutParameters.Gravity = GravityFlags.Center; | |||||
layoutParameters.SetMargins(0, 0, 0, 0); | |||||
break; | |||||
} | |||||
LayoutParameters = layoutParameters; | |||||
} | |||||
private int DipToPixels(int dip) | |||||
{ | |||||
return (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, dip, Resources.DisplayMetrics); | |||||
} | |||||
public new string Text | |||||
{ | |||||
get { return base.Text; } | |||||
set | |||||
{ | |||||
base.Text = value; | |||||
if (Visibility == ViewStates.Visible && string.IsNullOrEmpty(value)) | |||||
{ | |||||
Hide(true); | |||||
} | |||||
else if (Visibility == ViewStates.Gone && !string.IsNullOrEmpty(value)) | |||||
{ | |||||
Show(true); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,142 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms.Platform.Android.AppCompat; | |||||
using Xamarin.Forms; | |||||
using Android.Support.Design.Widget; | |||||
using Android.Views; | |||||
using Android.Widget; | |||||
using Xamarin.Forms.Platform.Android; | |||||
using eShopOnContainers.Droid.Extensions; | |||||
using eShopOnContainers.Core.Controls; | |||||
using eShopOnContainers.Droid.Renderers; | |||||
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))] | |||||
namespace eShopOnContainers.Droid.Renderers | |||||
{ | |||||
public class CustomTabbedPageRenderer : TabbedPageRenderer | |||||
{ | |||||
private const int DeleayBeforeTabAdded = 10; | |||||
protected readonly Dictionary<Element, BadgeView> BadgeViews = new Dictionary<Element, BadgeView>(); | |||||
private TabLayout _tabLayout; | |||||
private TabLayout.SlidingTabStrip _tabStrip; | |||||
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
_tabLayout = ViewGroup.FindChildOfType<TabLayout>(); | |||||
if (_tabLayout == null) | |||||
{ | |||||
Console.WriteLine("No TabLayout found. Bedge not added."); | |||||
return; | |||||
} | |||||
_tabStrip = _tabLayout.FindChildOfType<TabLayout.SlidingTabStrip>(); | |||||
for (var i = 0; i < _tabLayout.TabCount; i++) | |||||
{ | |||||
AddTabBadge(i); | |||||
} | |||||
Element.ChildAdded += OnTabAdded; | |||||
Element.ChildRemoved += OnTabRemoved; | |||||
} | |||||
private void AddTabBadge(int tabIndex) | |||||
{ | |||||
var element = Element.Children[tabIndex]; | |||||
var view = _tabLayout?.GetTabAt(tabIndex).CustomView ?? _tabStrip?.GetChildAt(tabIndex); | |||||
var badgeView = (view as ViewGroup)?.FindChildOfType<BadgeView>(); | |||||
if (badgeView == null) | |||||
{ | |||||
var imageView = (view as ViewGroup)?.FindChildOfType<ImageView>(); | |||||
var badgeTarget = imageView?.Drawable != null | |||||
? (Android.Views.View)imageView | |||||
: (view as ViewGroup)?.FindChildOfType<TextView>(); | |||||
// Create badge for tab | |||||
badgeView = new BadgeView(Context, badgeTarget); | |||||
} | |||||
BadgeViews[element] = badgeView; | |||||
// Get text | |||||
var badgeText = CustomTabbedPage.GetBadgeText(element); | |||||
badgeView.Text = badgeText; | |||||
// Set color if not default | |||||
var tabColor = CustomTabbedPage.GetBadgeColor(element); | |||||
if (tabColor != Color.Default) | |||||
{ | |||||
badgeView.BadgeColor = tabColor.ToAndroid(); | |||||
} | |||||
element.PropertyChanged += OnTabbedPagePropertyChanged; | |||||
} | |||||
protected virtual void OnTabbedPagePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) | |||||
{ | |||||
var element = sender as Element; | |||||
if (element == null) | |||||
return; | |||||
BadgeView badgeView; | |||||
if (!BadgeViews.TryGetValue(element, out badgeView)) | |||||
{ | |||||
return; | |||||
} | |||||
if (e.PropertyName == CustomTabbedPage.BadgeTextProperty.PropertyName) | |||||
{ | |||||
badgeView.Text = CustomTabbedPage.GetBadgeText(element); | |||||
return; | |||||
} | |||||
if (e.PropertyName == CustomTabbedPage.BadgeColorProperty.PropertyName) | |||||
{ | |||||
badgeView.BadgeColor = CustomTabbedPage.GetBadgeColor(element).ToAndroid(); | |||||
} | |||||
} | |||||
private void OnTabRemoved(object sender, ElementEventArgs e) | |||||
{ | |||||
e.Element.PropertyChanged -= OnTabbedPagePropertyChanged; | |||||
BadgeViews.Remove(e.Element); | |||||
} | |||||
private async void OnTabAdded(object sender, ElementEventArgs e) | |||||
{ | |||||
await Task.Delay(DeleayBeforeTabAdded); | |||||
var page = e.Element as Page; | |||||
if (page == null) | |||||
return; | |||||
var tabIndex = Element.Children.IndexOf(page); | |||||
AddTabBadge(tabIndex); | |||||
} | |||||
protected override void Dispose(bool disposing) | |||||
{ | |||||
if (Element != null) | |||||
{ | |||||
foreach (var tab in Element.Children) | |||||
{ | |||||
tab.PropertyChanged -= OnTabbedPagePropertyChanged; | |||||
} | |||||
Element.ChildRemoved -= OnTabRemoved; | |||||
Element.ChildAdded -= OnTabAdded; | |||||
BadgeViews.Clear(); | |||||
} | |||||
base.Dispose(disposing); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,45 @@ | |||||
using SlideOverKit.Droid; | |||||
using eShopOnContainers.Core.Views; | |||||
using eShopOnContainers.Droid.Renderers; | |||||
using System; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Platform.Android; | |||||
[assembly: ExportRenderer(typeof(HomeView), typeof(SlideDownMenuPageRenderer))] | |||||
namespace eShopOnContainers.Droid.Renderers | |||||
{ | |||||
public class SlideDownMenuPageRenderer : PageRenderer, ISlideOverKitPageRendererDroid | |||||
{ | |||||
public Action<ElementChangedEventArgs<Page>> OnElementChangedEvent { get; set; } | |||||
public Action<bool, int, int, int, int> OnLayoutEvent { get; set; } | |||||
public Action<int, int, int, int> OnSizeChangedEvent { get; set; } | |||||
public SlideDownMenuPageRenderer() | |||||
{ | |||||
new SlideOverKitDroidHandler().Init(this); | |||||
} | |||||
protected override void OnElementChanged(ElementChangedEventArgs<Page> e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
if (OnElementChangedEvent != null) | |||||
OnElementChangedEvent(e); | |||||
} | |||||
protected override void OnLayout(bool changed, int l, int t, int r, int b) | |||||
{ | |||||
base.OnLayout(changed, l, t, r, b); | |||||
if (OnLayoutEvent != null) | |||||
OnLayoutEvent(changed, l, t, r, b); | |||||
} | |||||
protected override void OnSizeChanged(int w, int h, int oldw, int oldh) | |||||
{ | |||||
base.OnSizeChanged(w, h, oldw, oldh); | |||||
if (OnSizeChangedEvent != null) | |||||
OnSizeChangedEvent(w, h, oldw, oldh); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,50 @@ | |||||
Images, layout descriptions, binary blobs and string dictionaries can be included | |||||
in your application as resource files. Various Android APIs are designed to | |||||
operate on the resource IDs instead of dealing with images, strings or binary blobs | |||||
directly. | |||||
For example, a sample Android app that contains a user interface layout (main.xml), | |||||
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) | |||||
would keep its resources in the "Resources" directory of the application: | |||||
Resources/ | |||||
drawable-hdpi/ | |||||
icon.png | |||||
drawable-ldpi/ | |||||
icon.png | |||||
drawable-mdpi/ | |||||
icon.png | |||||
layout/ | |||||
main.xml | |||||
values/ | |||||
strings.xml | |||||
In order to get the build system to recognize Android resources, set the build action to | |||||
"AndroidResource". The native Android APIs do not operate directly with filenames, but | |||||
instead operate on resource IDs. When you compile an Android application that uses resources, | |||||
the build system will package the resources for distribution and generate a class called | |||||
"Resource" that contains the tokens for each one of the resources included. For example, | |||||
for the above Resources layout, this is what the Resource class would expose: | |||||
public class Resource { | |||||
public class drawable { | |||||
public const int icon = 0x123; | |||||
} | |||||
public class layout { | |||||
public const int main = 0x456; | |||||
} | |||||
public class strings { | |||||
public const int first_string = 0xabc; | |||||
public const int second_string = 0xbcd; | |||||
} | |||||
} | |||||
You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main | |||||
to reference the layout/main.xml file, or Resource.strings.first_string to reference the first | |||||
string in the dictionary file values/strings.xml. |