Merge pull request #125 from dotnet/xamarin
Xamarin mobile client updates to reflect the code cleanup performed for the eBook.
This commit is contained in:
		
						commit
						dcd3057bee
					
				@ -3,7 +3,7 @@
 | 
			
		||||
             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"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
 | 
			
		||||
             x:Class="eShopOnContainers.App">
 | 
			
		||||
    <Application.Resources>
 | 
			
		||||
        <ResourceDictionary MergedWith="light:LightThemeResources">
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
            <Color x:Key="GreenColor">#00A69C</Color>
 | 
			
		||||
            <Color x:Key="DarkGreenColor">#00857D</Color>
 | 
			
		||||
            <Color x:Key="GrayColor">#e2e2e2</Color>
 | 
			
		||||
            <Color x:Key="ErrorColor">#ff5252</Color>
 | 
			
		||||
            
 | 
			
		||||
            <!-- FONTS -->
 | 
			
		||||
            <OnPlatform 
 | 
			
		||||
@ -100,6 +101,7 @@
 | 
			
		||||
            <!-- CONVERTERS -->
 | 
			
		||||
            <converters:CountToBoolConverter x:Key="CountToBoolConverter" />
 | 
			
		||||
            <converters:DatetimeConverter x:Key="DatetimeConverter" />
 | 
			
		||||
			<converters:FirstValidationErrorConverter x:Key="FirstValidationErrorConverter" />
 | 
			
		||||
            <converters:ImageConverter x:Key="ImageConverter" />
 | 
			
		||||
            <converters:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" />
 | 
			
		||||
            <converters:InverseCountToBoolConverter x:Key="InverseCountToBoolConverter" />
 | 
			
		||||
@ -109,6 +111,14 @@
 | 
			
		||||
			<converters:WebNavigatingEventArgsConverter x:Key="WebNavigatingEventArgsConverter" />
 | 
			
		||||
            
 | 
			
		||||
            <!-- STYLES -->
 | 
			
		||||
            <Style x:Key="ValidationErrorLabelStyle"
 | 
			
		||||
				   TargetType="{x:Type Label}">
 | 
			
		||||
				   <Setter Property="TextColor"
 | 
			
		||||
						   Value="{StaticResource ErrorColor}" />
 | 
			
		||||
				   <Setter Property="FontSize"
 | 
			
		||||
					       Value="{StaticResource LittleSize}" />
 | 
			
		||||
 			</Style>
 | 
			
		||||
			
 | 
			
		||||
            <Style x:Key="EntryStyle"
 | 
			
		||||
                   TargetType="{x:Type Entry}">
 | 
			
		||||
                <Setter Property="FontFamily"
 | 
			
		||||
@ -125,9 +135,9 @@
 | 
			
		||||
                        Value="Bold" />
 | 
			
		||||
                <Setter Property="Opacity"
 | 
			
		||||
                        Value="0.6" />
 | 
			
		||||
                <Setter Property="effects:LineColorEffect.ApplyLineColor"
 | 
			
		||||
                <Setter Property="behaviors:LineColorBehavior.ApplyLineColor"
 | 
			
		||||
                        Value="True" />
 | 
			
		||||
                <Setter Property="effects:LineColorEffect.LineColor"
 | 
			
		||||
                <Setter Property="behaviors:LineColorBehavior.LineColor"
 | 
			
		||||
                        Value="{StaticResource BlackColor}" />
 | 
			
		||||
                <Style.Triggers>
 | 
			
		||||
                    <Trigger TargetType="Entry"
 | 
			
		||||
@ -156,16 +166,16 @@
 | 
			
		||||
                        Value="Transparent" />
 | 
			
		||||
                <Setter Property="Opacity"
 | 
			
		||||
                        Value="0.6" />
 | 
			
		||||
                <Setter Property="effects:LineColorEffect.ApplyLineColor"
 | 
			
		||||
                <Setter Property="behaviors:LineColorBehavior.ApplyLineColor"
 | 
			
		||||
                        Value="True" />
 | 
			
		||||
                <Setter Property="effects:LineColorEffect.LineColor"
 | 
			
		||||
                <Setter Property="behaviors:LineColorBehavior.LineColor"
 | 
			
		||||
                        Value="Gray" />
 | 
			
		||||
                <Style.Triggers>
 | 
			
		||||
                    <Trigger TargetType="Entry"
 | 
			
		||||
                       Property="IsFocused"
 | 
			
		||||
                       Value="True">
 | 
			
		||||
                        <Setter Property="Opacity" Value="1" />
 | 
			
		||||
                        <Setter Property="effects:LineColorEffect.LineColor"                        
 | 
			
		||||
                        <Setter Property="behaviors:LineColorBehavior.LineColor"                        
 | 
			
		||||
                                Value="{StaticResource GreenColor}" />
 | 
			
		||||
                    </Trigger>
 | 
			
		||||
                </Style.Triggers>
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Services;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using Xamarin.Forms.Xaml;
 | 
			
		||||
@ -27,13 +27,13 @@ namespace eShopOnContainers
 | 
			
		||||
        private void InitApp()
 | 
			
		||||
        {
 | 
			
		||||
            UseMockServices = Settings.UseMocks;
 | 
			
		||||
 | 
			
		||||
            ViewModelLocator.Instance.UpdateDependencies(UseMockServices);
 | 
			
		||||
			ViewModelLocator.Initialize();
 | 
			
		||||
            ViewModelLocator.UpdateDependencies(UseMockServices);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task InitNavigation()
 | 
			
		||||
        {
 | 
			
		||||
            var navigationService = ViewModelLocator.Instance.Resolve<INavigationService>();
 | 
			
		||||
            var navigationService = ViewModelLocator.Resolve<INavigationService>();
 | 
			
		||||
            return navigationService.InitializeAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,18 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using eShopOnContainers.Core.Effects;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.Effects
 | 
			
		||||
namespace eShopOnContainers.Core.Behaviors
 | 
			
		||||
{
 | 
			
		||||
    public static class LineColorEffect
 | 
			
		||||
    public static class LineColorBehavior
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly BindableProperty ApplyLineColorProperty =
 | 
			
		||||
            BindableProperty.CreateAttached("ApplyLineColor", typeof(bool), typeof(LineColorEffect), false, 
 | 
			
		||||
            BindableProperty.CreateAttached("ApplyLineColor", typeof(bool), typeof(LineColorBehavior), false, 
 | 
			
		||||
                propertyChanged: OnApplyLineColorChanged);
 | 
			
		||||
 | 
			
		||||
		public static readonly BindableProperty LineColorProperty =
 | 
			
		||||
			BindableProperty.CreateAttached("LineColor", typeof(Color), typeof(LineColorBehavior), Color.Default);
 | 
			
		||||
 | 
			
		||||
        public static bool GetApplyLineColor(BindableObject view)
 | 
			
		||||
        {
 | 
			
		||||
            return (bool)view.GetValue(ApplyLineColorProperty);
 | 
			
		||||
@ -19,6 +23,16 @@ namespace eShopOnContainers.Core.Effects
 | 
			
		||||
            view.SetValue(ApplyLineColorProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		public static Color GetLineColor(BindableObject view)
 | 
			
		||||
		{
 | 
			
		||||
			return (Color)view.GetValue(LineColorProperty);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void SetLineColor(BindableObject view, Color value)
 | 
			
		||||
		{
 | 
			
		||||
			view.SetValue(LineColorProperty, value);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        private static void OnApplyLineColorChanged(BindableObject bindable, object oldValue, object newValue)
 | 
			
		||||
        {
 | 
			
		||||
            var view = bindable as View;
 | 
			
		||||
@ -28,9 +42,9 @@ namespace eShopOnContainers.Core.Effects
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            bool hasShadow = (bool)newValue;
 | 
			
		||||
            bool hasLine = (bool)newValue;
 | 
			
		||||
 | 
			
		||||
            if (hasShadow)
 | 
			
		||||
            if (hasLine)
 | 
			
		||||
            {
 | 
			
		||||
                view.Effects.Add(new EntryLineColorEffect());
 | 
			
		||||
            }
 | 
			
		||||
@ -43,25 +57,5 @@ namespace eShopOnContainers.Core.Effects
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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("eShopOnContainers.EntryLineColorEffect")
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.Converters
 | 
			
		||||
{
 | 
			
		||||
	public class FirstValidationErrorConverter : IValueConverter
 | 
			
		||||
	{
 | 
			
		||||
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 | 
			
		||||
		{
 | 
			
		||||
			ICollection<string> errors = value as ICollection<string>;
 | 
			
		||||
			return errors != null && errors.Count > 0 ? errors.ElementAt(0) : null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.Effects
 | 
			
		||||
{
 | 
			
		||||
	public class EntryLineColorEffect : RoutingEffect
 | 
			
		||||
	{
 | 
			
		||||
		public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
using eShopOnContainers.Core.Models.Basket;
 | 
			
		||||
using eShopOnContainers.Core.Models.Catalog;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
@ -21,7 +21,7 @@ namespace eShopOnContainers.Core.Helpers
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (!ViewModelLocator.Instance.UseMockService
 | 
			
		||||
                if (!ViewModelLocator.UseMockService
 | 
			
		||||
                    && Settings.UrlBase != GlobalSetting.DefaultEndpoint)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var catalogItem in catalogItems)
 | 
			
		||||
@ -54,7 +54,7 @@ namespace eShopOnContainers.Core.Helpers
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (!ViewModelLocator.Instance.UseMockService
 | 
			
		||||
                if (!ViewModelLocator.UseMockService
 | 
			
		||||
                    && Settings.UrlBase != GlobalSetting.DefaultEndpoint)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var basketItem in basketItems)
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using Plugin.Settings;
 | 
			
		||||
using Plugin.Settings.Abstractions;
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ namespace eShopOnContainers.Core.Helpers
 | 
			
		||||
        private const string IdUrlBase = "url_base";
 | 
			
		||||
        private static readonly string AccessTokenDefault = string.Empty;
 | 
			
		||||
        private static readonly string IdTokenDefault = string.Empty;
 | 
			
		||||
        private static readonly bool UseMocksDefault = ViewModelLocator.Instance.UseMockService;
 | 
			
		||||
		private static readonly bool UseMocksDefault = true;
 | 
			
		||||
        private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using System;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Services
 | 
			
		||||
@ -12,12 +11,6 @@ namespace eShopOnContainers.Services
 | 
			
		||||
 | 
			
		||||
        Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;
 | 
			
		||||
 | 
			
		||||
        Task NavigateToAsync(Type viewModelType);
 | 
			
		||||
 | 
			
		||||
        Task NavigateToAsync(Type viewModelType, object parameter);
 | 
			
		||||
 | 
			
		||||
        Task NavigateBackAsync();
 | 
			
		||||
 | 
			
		||||
        Task RemoveLastFromBackStackAsync();
 | 
			
		||||
 | 
			
		||||
        Task RemoveBackStackAsync();
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,10 @@
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels;
 | 
			
		||||
using eShopOnContainers.Core.Views;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
@ -11,23 +12,6 @@ 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()
 | 
			
		||||
        {
 | 
			
		||||
            if(string.IsNullOrEmpty(Settings.AuthAccessToken))
 | 
			
		||||
@ -46,32 +30,9 @@ namespace eShopOnContainers.Services
 | 
			
		||||
            return InternalNavigateToAsync(typeof(TViewModel), parameter);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task NavigateToAsync(Type viewModelType)
 | 
			
		||||
        public Task RemoveLastFromBackStackAsync()
 | 
			
		||||
        {
 | 
			
		||||
            return InternalNavigateToAsync(viewModelType, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task NavigateToAsync(Type viewModelType, object parameter)
 | 
			
		||||
        {
 | 
			
		||||
            return InternalNavigateToAsync(viewModelType, parameter);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task NavigateBackAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (CurrentApplication.MainPage is CatalogView)
 | 
			
		||||
            {
 | 
			
		||||
                var mainPage = CurrentApplication.MainPage as CatalogView;
 | 
			
		||||
                await mainPage.Navigation.PopAsync();
 | 
			
		||||
            }
 | 
			
		||||
            else if (CurrentApplication.MainPage != null)
 | 
			
		||||
            {
 | 
			
		||||
                await CurrentApplication.MainPage.Navigation.PopAsync();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public virtual Task RemoveLastFromBackStackAsync()
 | 
			
		||||
        {
 | 
			
		||||
            var mainPage = CurrentApplication.MainPage as CustomNavigationView;
 | 
			
		||||
            var mainPage = Application.Current.MainPage as CustomNavigationView;
 | 
			
		||||
 | 
			
		||||
            if (mainPage != null)
 | 
			
		||||
            {
 | 
			
		||||
@ -82,9 +43,9 @@ namespace eShopOnContainers.Services
 | 
			
		||||
            return Task.FromResult(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public virtual Task RemoveBackStackAsync()
 | 
			
		||||
        public Task RemoveBackStackAsync()
 | 
			
		||||
        {
 | 
			
		||||
            var mainPage = CurrentApplication.MainPage as CustomNavigationView;
 | 
			
		||||
            var mainPage = Application.Current.MainPage as CustomNavigationView;
 | 
			
		||||
 | 
			
		||||
            if (mainPage != null)
 | 
			
		||||
            {
 | 
			
		||||
@ -98,67 +59,49 @@ namespace eShopOnContainers.Services
 | 
			
		||||
            return Task.FromResult(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected virtual async Task InternalNavigateToAsync(Type viewModelType, object parameter)
 | 
			
		||||
        private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
 | 
			
		||||
        {
 | 
			
		||||
            Page page = CreateAndBindPage(viewModelType, parameter);
 | 
			
		||||
            Page page = CreatePage(viewModelType, parameter);
 | 
			
		||||
 | 
			
		||||
            if (page is LoginView)
 | 
			
		||||
            {
 | 
			
		||||
                CurrentApplication.MainPage = new CustomNavigationView(page);
 | 
			
		||||
                Application.Current.MainPage = new CustomNavigationView(page);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var navigationPage = CurrentApplication.MainPage as CustomNavigationView;
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
                var navigationPage = Application.Current.MainPage as CustomNavigationView;
 | 
			
		||||
                if (navigationPage != null)
 | 
			
		||||
                {
 | 
			
		||||
                    await navigationPage.PushAsync(page);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    CurrentApplication.MainPage = new CustomNavigationView(page);
 | 
			
		||||
                    Application.Current.MainPage = new CustomNavigationView(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");
 | 
			
		||||
            }
 | 
			
		||||
		private Type GetPageTypeForViewModel(Type viewModelType)
 | 
			
		||||
		{
 | 
			
		||||
			var viewName = viewModelType.FullName.Replace("Model", string.Empty);
 | 
			
		||||
			var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;
 | 
			
		||||
			var viewAssemblyName = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);
 | 
			
		||||
			var viewType = Type.GetType(viewAssemblyName);
 | 
			
		||||
			return viewType;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
            return _mappings[viewModelType];
 | 
			
		||||
        }
 | 
			
		||||
		private Page CreatePage(Type viewModelType, object parameter)
 | 
			
		||||
		{
 | 
			
		||||
			Type pageType = GetPageTypeForViewModel(viewModelType);
 | 
			
		||||
			if (pageType == null)
 | 
			
		||||
			{
 | 
			
		||||
				throw new Exception($"Cannot locate page type for {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(BasketViewModel), typeof(BasketView));
 | 
			
		||||
            _mappings.Add(typeof(CatalogViewModel), typeof(CatalogView));
 | 
			
		||||
            _mappings.Add(typeof(CheckoutViewModel), typeof(CheckoutView));
 | 
			
		||||
            _mappings.Add(typeof(LoginViewModel), typeof(LoginView));
 | 
			
		||||
            _mappings.Add(typeof(MainViewModel), typeof(MainView));
 | 
			
		||||
            _mappings.Add(typeof(OrderDetailViewModel), typeof(OrderDetailView));
 | 
			
		||||
            _mappings.Add(typeof(ProfileViewModel), typeof(ProfileView));
 | 
			
		||||
            _mappings.Add(typeof(SettingsViewModel), typeof(SettingsView));
 | 
			
		||||
        }
 | 
			
		||||
			Page page = Activator.CreateInstance(pageType) as Page;
 | 
			
		||||
			return page;
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.Validations
 | 
			
		||||
@ -8,13 +7,24 @@ namespace eShopOnContainers.Core.Validations
 | 
			
		||||
    public class ValidatableObject<T> : ExtendedBindableObject, IValidity
 | 
			
		||||
    {
 | 
			
		||||
        private readonly List<IValidationRule<T>> _validations;
 | 
			
		||||
        private readonly ObservableCollection<string> _errors;
 | 
			
		||||
		private List<string> _errors;
 | 
			
		||||
        private T _value;
 | 
			
		||||
        private bool _isValid;
 | 
			
		||||
 | 
			
		||||
        public List<IValidationRule<T>> Validations => _validations;
 | 
			
		||||
 | 
			
		||||
        public ObservableCollection<string> Errors => _errors;
 | 
			
		||||
		public List<string> Errors
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return _errors;
 | 
			
		||||
			}
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				_errors = value;
 | 
			
		||||
				RaisePropertyChanged(() => Errors);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        public T Value
 | 
			
		||||
        {
 | 
			
		||||
@ -22,7 +32,6 @@ namespace eShopOnContainers.Core.Validations
 | 
			
		||||
            {
 | 
			
		||||
                return _value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _value = value;
 | 
			
		||||
@ -36,11 +45,9 @@ namespace eShopOnContainers.Core.Validations
 | 
			
		||||
            {
 | 
			
		||||
                return _isValid;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _isValid = value;
 | 
			
		||||
                _errors.Clear();
 | 
			
		||||
                RaisePropertyChanged(() => IsValid);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -48,7 +55,7 @@ namespace eShopOnContainers.Core.Validations
 | 
			
		||||
        public ValidatableObject()
 | 
			
		||||
        {
 | 
			
		||||
            _isValid = true;
 | 
			
		||||
            _errors = new ObservableCollection<string>();
 | 
			
		||||
            _errors = new List<string>();
 | 
			
		||||
            _validations = new List<IValidationRule<T>>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -59,11 +66,7 @@ namespace eShopOnContainers.Core.Validations
 | 
			
		||||
            IEnumerable<string> errors = _validations.Where(v => !v.Check(Value))                             
 | 
			
		||||
                .Select(v => v.ValidationMessage);
 | 
			
		||||
 | 
			
		||||
            foreach (var error in errors)
 | 
			
		||||
            {
 | 
			
		||||
                Errors.Add(error);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
			Errors = errors.ToList();
 | 
			
		||||
            IsValid = !Errors.Any();
 | 
			
		||||
 | 
			
		||||
            return this.IsValid;
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ using System.Linq.Expressions;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.ViewModels.Base
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels.Base
 | 
			
		||||
{
 | 
			
		||||
    public abstract class ExtendedBindableObject : BindableObject
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels.Base
 | 
			
		||||
{
 | 
			
		||||
    public class MessengerKeys
 | 
			
		||||
    public class MessageKeys
 | 
			
		||||
    {
 | 
			
		||||
        // Add product to basket
 | 
			
		||||
        public const string AddProduct = "AddProduct";
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
using eShopOnContainers.Core;
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Services;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.ViewModels.Base
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels.Base
 | 
			
		||||
{
 | 
			
		||||
    public abstract class ViewModelBase : ExtendedBindableObject
 | 
			
		||||
    {
 | 
			
		||||
@ -28,8 +27,8 @@ namespace eShopOnContainers.ViewModels.Base
 | 
			
		||||
 | 
			
		||||
        public ViewModelBase()
 | 
			
		||||
        {
 | 
			
		||||
            DialogService = ViewModelLocator.Instance.Resolve<IDialogService>();
 | 
			
		||||
            NavigationService = ViewModelLocator.Instance.Resolve<INavigationService>();
 | 
			
		||||
            DialogService = ViewModelLocator.Resolve<IDialogService>();
 | 
			
		||||
            NavigationService = ViewModelLocator.Resolve<INavigationService>();
 | 
			
		||||
            GlobalSetting.Instance.BaseEndpoint = Settings.UrlBase;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
using Microsoft.Practices.Unity;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels;
 | 
			
		||||
using eShopOnContainers.Services;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using eShopOnContainers.Core.Services.Catalog;
 | 
			
		||||
using eShopOnContainers.Core.Services.OpenUrl;
 | 
			
		||||
using eShopOnContainers.Core.Services.RequestProvider;
 | 
			
		||||
@ -9,100 +10,101 @@ using eShopOnContainers.Core.Services.Basket;
 | 
			
		||||
using eShopOnContainers.Core.Services.Identity;
 | 
			
		||||
using eShopOnContainers.Core.Services.Order;
 | 
			
		||||
using eShopOnContainers.Core.Services.User;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.ViewModels.Base
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels.Base
 | 
			
		||||
{
 | 
			
		||||
    public class ViewModelLocator
 | 
			
		||||
    public static class ViewModelLocator
 | 
			
		||||
    {
 | 
			
		||||
        private bool _useMockService;
 | 
			
		||||
        private readonly IUnityContainer _unityContainer;
 | 
			
		||||
		private static readonly IUnityContainer _unityContainer = new UnityContainer();
 | 
			
		||||
 | 
			
		||||
        private static readonly ViewModelLocator _instance = new ViewModelLocator();
 | 
			
		||||
		public static readonly BindableProperty AutoWireViewModelProperty =
 | 
			
		||||
			BindableProperty.CreateAttached("AutoWireViewModel", typeof(bool), typeof(ViewModelLocator), default(bool), propertyChanged: OnAutoWireViewModelChanged);
 | 
			
		||||
 | 
			
		||||
        public static ViewModelLocator Instance
 | 
			
		||||
        {
 | 
			
		||||
            get { return _instance; }
 | 
			
		||||
        }
 | 
			
		||||
		public static bool GetAutoWireViewModel(BindableObject bindable)
 | 
			
		||||
		{
 | 
			
		||||
			return (bool)bindable.GetValue(ViewModelLocator.AutoWireViewModelProperty);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        public bool UseMockService
 | 
			
		||||
        {
 | 
			
		||||
            get { return _useMockService; }
 | 
			
		||||
            set { _useMockService = value; ; }
 | 
			
		||||
        }
 | 
			
		||||
		public static void SetAutoWireViewModel(BindableObject bindable, bool value)
 | 
			
		||||
		{
 | 
			
		||||
			bindable.SetValue(ViewModelLocator.AutoWireViewModelProperty, value);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        protected ViewModelLocator()
 | 
			
		||||
        {
 | 
			
		||||
            _unityContainer = new UnityContainer();
 | 
			
		||||
		public static bool UseMockService { get; set; }
 | 
			
		||||
 | 
			
		||||
            // Services
 | 
			
		||||
            _unityContainer.RegisterType<IDialogService, DialogService>();
 | 
			
		||||
            RegisterSingleton<INavigationService, NavigationService>();
 | 
			
		||||
            _unityContainer.RegisterType<IOpenUrlService, OpenUrlService>();
 | 
			
		||||
            _unityContainer.RegisterType<IRequestProvider, RequestProvider>();
 | 
			
		||||
            _unityContainer.RegisterType<IIdentityService, IdentityService>();
 | 
			
		||||
		public static void Initialize()
 | 
			
		||||
		{
 | 
			
		||||
			// Services
 | 
			
		||||
			_unityContainer.RegisterType<IDialogService, DialogService>();
 | 
			
		||||
			_unityContainer.RegisterType<INavigationService, NavigationService>(new ContainerControlledLifetimeManager());
 | 
			
		||||
			_unityContainer.RegisterType<IOpenUrlService, OpenUrlService>();
 | 
			
		||||
			_unityContainer.RegisterType<IRequestProvider, RequestProvider>();
 | 
			
		||||
			_unityContainer.RegisterType<IIdentityService, IdentityService>();
 | 
			
		||||
			_unityContainer.RegisterType<ICatalogService, CatalogMockService>();
 | 
			
		||||
			_unityContainer.RegisterType<IBasketService, BasketMockService>();
 | 
			
		||||
			_unityContainer.RegisterType<IUserService, UserMockService>();
 | 
			
		||||
 | 
			
		||||
            _unityContainer.RegisterType<ICatalogService, CatalogMockService>();
 | 
			
		||||
            _unityContainer.RegisterType<IBasketService, BasketMockService>();
 | 
			
		||||
            _unityContainer.RegisterType<IUserService, UserMockService>();
 | 
			
		||||
			// View models
 | 
			
		||||
			_unityContainer.RegisterType<BasketViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<CatalogViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<CheckoutViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<LoginViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<MainViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<OrderDetailViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<ProfileViewModel>();
 | 
			
		||||
			_unityContainer.RegisterType<SettingsViewModel>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
            // View models
 | 
			
		||||
            _unityContainer.RegisterType<BasketViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<CatalogViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<CheckoutViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<LoginViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<MainViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<OrderDetailViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<ProfileViewModel>();
 | 
			
		||||
            _unityContainer.RegisterType<SettingsViewModel>();
 | 
			
		||||
        }
 | 
			
		||||
		public static void UpdateDependencies(bool useMockServices)
 | 
			
		||||
		{
 | 
			
		||||
			// Change injected dependencies
 | 
			
		||||
			if (useMockServices)
 | 
			
		||||
			{
 | 
			
		||||
				_unityContainer.RegisterInstance<ICatalogService>(new CatalogMockService());
 | 
			
		||||
				_unityContainer.RegisterInstance<IBasketService>(new BasketMockService());
 | 
			
		||||
				_unityContainer.RegisterInstance<IOrderService>(new OrderMockService());
 | 
			
		||||
				_unityContainer.RegisterInstance<IUserService>(new UserMockService());
 | 
			
		||||
 | 
			
		||||
        public void UpdateDependencies(bool useMockServices)
 | 
			
		||||
        {
 | 
			
		||||
            // Change injected dependencies
 | 
			
		||||
            if (useMockServices)
 | 
			
		||||
            {
 | 
			
		||||
                _unityContainer.RegisterInstance<ICatalogService>(new CatalogMockService());
 | 
			
		||||
                _unityContainer.RegisterInstance<IBasketService>(new BasketMockService());
 | 
			
		||||
                _unityContainer.RegisterInstance<IOrderService>(new OrderMockService());
 | 
			
		||||
                _unityContainer.RegisterInstance<IUserService>(new UserMockService());
 | 
			
		||||
				UseMockService = true;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				var requestProvider = Resolve<IRequestProvider>();
 | 
			
		||||
				_unityContainer.RegisterInstance<ICatalogService>(new CatalogService(requestProvider));
 | 
			
		||||
				_unityContainer.RegisterInstance<IBasketService>(new BasketService(requestProvider));
 | 
			
		||||
				_unityContainer.RegisterInstance<IOrderService>(new OrderService(requestProvider));
 | 
			
		||||
				_unityContainer.RegisterInstance<IUserService>(new UserService(requestProvider));
 | 
			
		||||
 | 
			
		||||
                UseMockService = true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var requestProvider = Resolve<IRequestProvider>();
 | 
			
		||||
                _unityContainer.RegisterInstance<ICatalogService>(new CatalogService(requestProvider));
 | 
			
		||||
                _unityContainer.RegisterInstance<IBasketService>(new BasketService(requestProvider));
 | 
			
		||||
                _unityContainer.RegisterInstance<IOrderService>(new OrderService(requestProvider));
 | 
			
		||||
                _unityContainer.RegisterInstance<IUserService>(new UserService(requestProvider));
 | 
			
		||||
				UseMockService = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
                UseMockService = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public T Resolve<T>()
 | 
			
		||||
        {
 | 
			
		||||
            return _unityContainer.Resolve<T>();
 | 
			
		||||
        }
 | 
			
		||||
		public static T Resolve<T>()
 | 
			
		||||
		{
 | 
			
		||||
			return _unityContainer.Resolve<T>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        public object Resolve(Type type)
 | 
			
		||||
        {
 | 
			
		||||
            return _unityContainer.Resolve(type);
 | 
			
		||||
        }
 | 
			
		||||
		private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
 | 
			
		||||
		{
 | 
			
		||||
			var view = bindable as Element;
 | 
			
		||||
			if (view == null)
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
        public void Register<T>(T instance)
 | 
			
		||||
        {
 | 
			
		||||
            _unityContainer.RegisterInstance<T>(instance);
 | 
			
		||||
        }
 | 
			
		||||
			var viewType = view.GetType();
 | 
			
		||||
			var viewName = viewType.FullName.Replace(".Views.", ".ViewModels.");
 | 
			
		||||
			var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
 | 
			
		||||
			var viewModelName = string.Format(CultureInfo.InvariantCulture, "{0}Model, {1}", viewName, viewAssemblyName);
 | 
			
		||||
 | 
			
		||||
        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());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
			var viewModelType = Type.GetType(viewModelName);
 | 
			
		||||
			if (viewModelType == null)
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			var viewModel = _unityContainer.Resolve(viewModelType);
 | 
			
		||||
			view.BindingContext = viewModel;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -4,8 +4,6 @@ using eShopOnContainers.Core.Models.Catalog;
 | 
			
		||||
using eShopOnContainers.Core.Services.Basket;
 | 
			
		||||
using eShopOnContainers.Core.Services.User;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
@ -61,7 +59,7 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ICommand AddCommand => new Command<BasketItem>(AddItem);
 | 
			
		||||
        public ICommand AddCommand => new Command<BasketItem>(async (item) => await AddItemAsync(item));
 | 
			
		||||
 | 
			
		||||
        public ICommand CheckoutCommand => new Command(async () => await CheckoutAsync());
 | 
			
		||||
 | 
			
		||||
@ -82,22 +80,22 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
                foreach (var basketItem in basket.Items)
 | 
			
		||||
                {
 | 
			
		||||
                    BadgeCount += basketItem.Quantity;
 | 
			
		||||
                    AddBasketItem(basketItem);
 | 
			
		||||
                    await AddBasketItemAsync(basketItem);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessengerKeys.AddProduct);
 | 
			
		||||
            MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(this, MessengerKeys.AddProduct, (sender, arg) =>
 | 
			
		||||
            MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct);
 | 
			
		||||
            MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct, async (sender, arg) =>
 | 
			
		||||
            {
 | 
			
		||||
                BadgeCount++;
 | 
			
		||||
 | 
			
		||||
                AddCatalogItem(arg);
 | 
			
		||||
                await AddCatalogItemAsync(arg);
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            await base.InitializeAsync(navigationData);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddCatalogItem(CatalogItem item)
 | 
			
		||||
        private async Task AddCatalogItemAsync(CatalogItem item)
 | 
			
		||||
        {
 | 
			
		||||
            BasketItems.Add(new BasketItem
 | 
			
		||||
            {
 | 
			
		||||
@ -108,26 +106,26 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
                Quantity = 1
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            ReCalculateTotal();
 | 
			
		||||
            await ReCalculateTotalAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddItem(BasketItem item)
 | 
			
		||||
        private async Task AddItemAsync(BasketItem item)
 | 
			
		||||
        {
 | 
			
		||||
            BadgeCount++;
 | 
			
		||||
 | 
			
		||||
            AddBasketItem(item);
 | 
			
		||||
            await AddBasketItemAsync(item);
 | 
			
		||||
 | 
			
		||||
            RaisePropertyChanged(() => BasketItems);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void AddBasketItem(BasketItem item)
 | 
			
		||||
        private async Task AddBasketItemAsync(BasketItem item)
 | 
			
		||||
        {
 | 
			
		||||
            BasketItems.Add(item);
 | 
			
		||||
 | 
			
		||||
            ReCalculateTotal();
 | 
			
		||||
            await ReCalculateTotalAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void ReCalculateTotal()
 | 
			
		||||
        private async Task ReCalculateTotalAsync()
 | 
			
		||||
        {
 | 
			
		||||
            Total = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,11 @@
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.Models.Catalog;
 | 
			
		||||
using eShopOnContainers.Core.Services.Catalog;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using eShopOnContainers.Core.Services.Basket;
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Core.Services.User;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
@ -20,19 +17,11 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
        private CatalogBrand _brand;
 | 
			
		||||
        private ObservableCollection<CatalogType> _types;
 | 
			
		||||
        private CatalogType _type;
 | 
			
		||||
 | 
			
		||||
        private IBasketService _basketService;
 | 
			
		||||
        private ICatalogService _productsService;
 | 
			
		||||
        private IUserService _userService;
 | 
			
		||||
 | 
			
		||||
        public CatalogViewModel(
 | 
			
		||||
            IBasketService basketService,
 | 
			
		||||
            ICatalogService productsService,
 | 
			
		||||
            IUserService userService)
 | 
			
		||||
        public CatalogViewModel(ICatalogService productsService)
 | 
			
		||||
        {
 | 
			
		||||
            _basketService = basketService;
 | 
			
		||||
            _productsService = productsService;
 | 
			
		||||
            _userService = userService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ObservableCollection<CatalogItem> Products
 | 
			
		||||
@ -91,9 +80,9 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
 | 
			
		||||
        public ICommand AddCatalogItemCommand => new Command<CatalogItem>(AddCatalogItem);
 | 
			
		||||
 | 
			
		||||
        public ICommand FilterCommand => new Command(Filter);
 | 
			
		||||
        public ICommand FilterCommand => new Command(async () => await FilterAsync());
 | 
			
		||||
 | 
			
		||||
        public ICommand ClearFilterCommand => new Command(ClearFilter);
 | 
			
		||||
		public ICommand ClearFilterCommand => new Command(async () => await ClearFilterAsync());
 | 
			
		||||
 | 
			
		||||
        public override async Task InitializeAsync(object navigationData)
 | 
			
		||||
        {
 | 
			
		||||
@ -110,10 +99,10 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
        private void AddCatalogItem(CatalogItem catalogItem)
 | 
			
		||||
        {
 | 
			
		||||
            // Add new item to Basket
 | 
			
		||||
            MessagingCenter.Send(this, MessengerKeys.AddProduct, catalogItem);
 | 
			
		||||
            MessagingCenter.Send(this, MessageKeys.AddProduct, catalogItem);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void Filter()
 | 
			
		||||
        private async Task FilterAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Brand == null && Type == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -123,13 +112,13 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
            IsBusy = true;
 | 
			
		||||
 | 
			
		||||
            // Filter catalog products
 | 
			
		||||
            MessagingCenter.Send(this, MessengerKeys.Filter);
 | 
			
		||||
            MessagingCenter.Send(this, MessageKeys.Filter);
 | 
			
		||||
            Products = await _productsService.FilterAsync(Brand.Id, Type.Id);
 | 
			
		||||
 | 
			
		||||
            IsBusy = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void ClearFilter()
 | 
			
		||||
        private async Task ClearFilterAsync()
 | 
			
		||||
        {
 | 
			
		||||
            IsBusy = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
using eShopOnContainers.Core.Models.Navigation;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
@ -138,7 +138,7 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
                await _basketService.ClearBasketAsync(_shippingAddress.Id.ToString(), authToken);
 | 
			
		||||
 | 
			
		||||
                // Reset Basket badge
 | 
			
		||||
                var basketViewModel = ViewModelLocator.Instance.Resolve<BasketViewModel>();
 | 
			
		||||
                var basketViewModel = ViewModelLocator.Resolve<BasketViewModel>();
 | 
			
		||||
                basketViewModel.BadgeCount = 0;
 | 
			
		||||
 | 
			
		||||
                // Navigate to Orders
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,8 @@
 | 
			
		||||
using eShopOnContainers.Core.Models.User;
 | 
			
		||||
using eShopOnContainers.Core.Services.Identity;
 | 
			
		||||
using eShopOnContainers.Core.Services.OpenUrl;
 | 
			
		||||
using eShopOnContainers.Core.Services.User;
 | 
			
		||||
using eShopOnContainers.Core.Validations;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using IdentityModel.Client;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
@ -25,16 +24,13 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
 | 
			
		||||
        private IOpenUrlService _openUrlService;
 | 
			
		||||
        private IIdentityService _identityService;
 | 
			
		||||
        private IUserService _userService;
 | 
			
		||||
 | 
			
		||||
        public LoginViewModel(
 | 
			
		||||
            IOpenUrlService openUrlService,
 | 
			
		||||
            IIdentityService identityService,
 | 
			
		||||
            IUserService userService)
 | 
			
		||||
            IIdentityService identityService)
 | 
			
		||||
        {
 | 
			
		||||
            _openUrlService = openUrlService;
 | 
			
		||||
            _identityService = identityService;
 | 
			
		||||
            _userService = userService;
 | 
			
		||||
 | 
			
		||||
            _userName = new ValidatableObject<string>();
 | 
			
		||||
            _password = new ValidatableObject<string>();
 | 
			
		||||
@ -131,6 +127,10 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
 | 
			
		||||
        public ICommand SettingsCommand => new Command(async () => await SettingsAsync());
 | 
			
		||||
 | 
			
		||||
		public ICommand ValidateUserNameCommand => new Command(() => ValidateUserName());
 | 
			
		||||
 | 
			
		||||
		public ICommand ValidatePasswordCommand => new Command(() => ValidatePassword());
 | 
			
		||||
 | 
			
		||||
        public override Task InitializeAsync(object navigationData)
 | 
			
		||||
        {
 | 
			
		||||
            if(navigationData is LogoutParameter)
 | 
			
		||||
@ -253,16 +253,26 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
 | 
			
		||||
        private bool Validate()
 | 
			
		||||
        {
 | 
			
		||||
            bool isValidUser = _userName.Validate();
 | 
			
		||||
            bool isValidPassword = _password.Validate();
 | 
			
		||||
			bool isValidUser = ValidateUserName();
 | 
			
		||||
            bool isValidPassword = ValidatePassword();
 | 
			
		||||
 | 
			
		||||
            return isValidUser && isValidPassword;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		private bool ValidateUserName()
 | 
			
		||||
		{
 | 
			
		||||
			return _userName.Validate();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool ValidatePassword()
 | 
			
		||||
		{
 | 
			
		||||
			return _password.Validate();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        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" });
 | 
			
		||||
            _userName.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "A username is required." });
 | 
			
		||||
            _password.Validations.Add(new IsNotNullOrEmptyRule<string> { ValidationMessage = "A password is required." });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void InvalidateMock()
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,7 @@
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.Models.Navigation;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
@ -19,7 +18,7 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
            {
 | 
			
		||||
                // Change selected application tab
 | 
			
		||||
                var tabIndex = ((TabParameter)navigationData).TabIndex;
 | 
			
		||||
                MessagingCenter.Send(this, MessengerKeys.ChangeTab, tabIndex);
 | 
			
		||||
                MessagingCenter.Send(this, MessageKeys.ChangeTab, tabIndex);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return base.InitializeAsync(navigationData);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using eShopOnContainers.Core.Models.Orders;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.Services.Catalog;
 | 
			
		||||
using eShopOnContainers.Core.Services.Basket;
 | 
			
		||||
using eShopOnContainers.Core.Services.Order;
 | 
			
		||||
@ -13,17 +13,10 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
    {
 | 
			
		||||
        private Order _order;
 | 
			
		||||
 | 
			
		||||
        private IBasketService _orderService;
 | 
			
		||||
        private ICatalogService _catalogService;
 | 
			
		||||
        private IOrderService _ordersService;
 | 
			
		||||
 | 
			
		||||
        public OrderDetailViewModel(
 | 
			
		||||
            IBasketService orderService,
 | 
			
		||||
            ICatalogService catalogService,
 | 
			
		||||
            IOrderService ordersService)
 | 
			
		||||
        public OrderDetailViewModel(IOrderService ordersService)
 | 
			
		||||
        {
 | 
			
		||||
            _orderService = orderService;
 | 
			
		||||
            _catalogService = catalogService;
 | 
			
		||||
            _ordersService = ordersService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Core.Models.Orders;
 | 
			
		||||
using eShopOnContainers.Core.Models.User;
 | 
			
		||||
using eShopOnContainers.Core.Services.Order;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
@ -71,7 +71,7 @@ namespace eShopOnContainers.Core.ViewModels
 | 
			
		||||
 | 
			
		||||
        private void MockServices()
 | 
			
		||||
        {
 | 
			
		||||
            ViewModelLocator.Instance.UpdateDependencies(!UseAzureServices);
 | 
			
		||||
            ViewModelLocator.UpdateDependencies(!UseAzureServices);
 | 
			
		||||
            UpdateInfo();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
<?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.BasketView"  
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.BasketView"
 | 
			
		||||
			 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core" 
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"   
 | 
			
		||||
             Title="Cart">
 | 
			
		||||
             viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
			 Title="Cart">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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.CatalogView"   
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"   
 | 
			
		||||
             xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
 | 
			
		||||
		     xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"      
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
             Title="Catalog">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
 | 
			
		||||
@ -8,17 +8,15 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
{
 | 
			
		||||
    public partial class CatalogView : ContentPage, IMenuContainerPage
 | 
			
		||||
    {
 | 
			
		||||
        private FiltersView _filterView;
 | 
			
		||||
        private FiltersView _filterView = new FiltersView();
 | 
			
		||||
 | 
			
		||||
        public CatalogView()
 | 
			
		||||
        {
 | 
			
		||||
            InitializeComponent();
 | 
			
		||||
 | 
			
		||||
            _filterView = new FiltersView();
 | 
			
		||||
 | 
			
		||||
            SlideMenu = _filterView;
 | 
			
		||||
 | 
			
		||||
            MessagingCenter.Subscribe<CatalogViewModel>(this, MessengerKeys.Filter, (sender) =>
 | 
			
		||||
            MessagingCenter.Subscribe<CatalogViewModel>(this, MessageKeys.Filter, (sender) =>
 | 
			
		||||
            {
 | 
			
		||||
                Filter();
 | 
			
		||||
            });
 | 
			
		||||
@ -42,7 +40,6 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
            set;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        protected override void OnBindingContextChanged()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnBindingContextChanged();
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,10 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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.CheckoutView"   
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"  
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.CheckoutView"
 | 
			
		||||
			 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
             Title="Checkout">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
@ -82,8 +84,7 @@
 | 
			
		||||
                    <RowDefinition Height="Auto" />
 | 
			
		||||
                </Grid.RowDefinitions>
 | 
			
		||||
                <!-- ORDER INFO -->
 | 
			
		||||
                <Grid 
 | 
			
		||||
                    x:Name="OrderInfo">
 | 
			
		||||
                <Grid>
 | 
			
		||||
                    <Grid.ColumnDefinitions>
 | 
			
		||||
                        <ColumnDefinition />
 | 
			
		||||
                        <ColumnDefinition />
 | 
			
		||||
@ -139,8 +140,7 @@
 | 
			
		||||
                </Grid>
 | 
			
		||||
                <!-- SHIPPING ADDRESS -->
 | 
			
		||||
                <Grid
 | 
			
		||||
                    x:Name="ShippingAddress"
 | 
			
		||||
                    Grid.Row="1"
 | 
			
		||||
					Grid.Row="1"
 | 
			
		||||
                    Margin="12">
 | 
			
		||||
                    <Grid.RowDefinitions>
 | 
			
		||||
                        <RowDefinition Height="Auto" />
 | 
			
		||||
@ -167,9 +167,7 @@
 | 
			
		||||
                    </StackLayout>
 | 
			
		||||
                </Grid>
 | 
			
		||||
                <!-- ORDER ITEMS -->
 | 
			
		||||
                <Grid            
 | 
			
		||||
                    x:Name="OrderItems"
 | 
			
		||||
                    Grid.Row="2">
 | 
			
		||||
                <Grid Grid.Row="2">
 | 
			
		||||
                    <Grid.RowDefinitions>
 | 
			
		||||
                        <RowDefinition Height="*" />
 | 
			
		||||
                        <RowDefinition Height="Auto" />
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,11 @@
 | 
			
		||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
 | 
			
		||||
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.LoginView"
 | 
			
		||||
		 	 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core">
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true">
 | 
			
		||||
    <ContentPage.Title>
 | 
			
		||||
        <OnPlatform
 | 
			
		||||
            x:TypeArguments="x:String"
 | 
			
		||||
@ -175,30 +177,60 @@
 | 
			
		||||
                Margin="24">
 | 
			
		||||
                <Label
 | 
			
		||||
                  Text="User name or email"
 | 
			
		||||
                  Style="{StaticResource HeaderLabelStyle}"/>
 | 
			
		||||
                <Entry
 | 
			
		||||
                    Text="{Binding UserName.Value, Mode=TwoWay}">
 | 
			
		||||
                    <Entry.Style>
 | 
			
		||||
                  Style="{StaticResource HeaderLabelStyle}" />
 | 
			
		||||
                <Entry Text="{Binding UserName.Value, Mode=TwoWay}">
 | 
			
		||||
					<Entry.Style>
 | 
			
		||||
                        <OnPlatform x:TypeArguments="Style"
 | 
			
		||||
                          iOS="{StaticResource EntryStyle}"
 | 
			
		||||
                          Android="{StaticResource EntryStyle}"
 | 
			
		||||
                          WinPhone="{StaticResource UwpEntryStyle}"/>
 | 
			
		||||
                    </Entry.Style>
 | 
			
		||||
                    <Entry.Behaviors>
 | 
			
		||||
						<behaviors:EventToCommandBehavior
 | 
			
		||||
							EventName="TextChanged"
 | 
			
		||||
							Command="{Binding ValidateUserNameCommand}" />
 | 
			
		||||
					</Entry.Behaviors>
 | 
			
		||||
					<Entry.Triggers>
 | 
			
		||||
						<DataTrigger 
 | 
			
		||||
							TargetType="Entry"
 | 
			
		||||
							Binding="{Binding UserName.IsValid}"
 | 
			
		||||
							Value="False">
 | 
			
		||||
							<Setter Property="behaviors:LineColorBehavior.LineColor" Value="{StaticResource ErrorColor}" />
 | 
			
		||||
						</DataTrigger>
 | 
			
		||||
					</Entry.Triggers>
 | 
			
		||||
                </Entry>
 | 
			
		||||
				<Label 
 | 
			
		||||
					Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}"
 | 
			
		||||
					Style="{StaticResource ValidationErrorLabelStyle}" />
 | 
			
		||||
                <Label
 | 
			
		||||
                  Text="Password"
 | 
			
		||||
                  Style="{StaticResource HeaderLabelStyle}"/>
 | 
			
		||||
                <Entry
 | 
			
		||||
                  IsPassword="True"
 | 
			
		||||
                  Text="{Binding Password.Value, Mode=TwoWay}"
 | 
			
		||||
                  Style="{StaticResource EntryStyle}">
 | 
			
		||||
                  Text="{Binding Password.Value, Mode=TwoWay}">
 | 
			
		||||
                    <Entry.Style>
 | 
			
		||||
                        <OnPlatform x:TypeArguments="Style"
 | 
			
		||||
                          iOS="{StaticResource EntryStyle}"
 | 
			
		||||
                          Android="{StaticResource EntryStyle}"
 | 
			
		||||
                          WinPhone="{StaticResource UwpEntryStyle}"/>
 | 
			
		||||
                    </Entry.Style>
 | 
			
		||||
					<Entry.Behaviors>
 | 
			
		||||
						<behaviors:EventToCommandBehavior
 | 
			
		||||
							EventName="TextChanged"
 | 
			
		||||
							Command="{Binding ValidatePasswordCommand}" />
 | 
			
		||||
					</Entry.Behaviors>
 | 
			
		||||
					<Entry.Triggers>
 | 
			
		||||
						<DataTrigger 
 | 
			
		||||
							TargetType="Entry"
 | 
			
		||||
							Binding="{Binding Password.IsValid}"
 | 
			
		||||
							Value="False">
 | 
			
		||||
							<Setter Property="behaviors:LineColorBehavior.LineColor" Value="{StaticResource ErrorColor}" />
 | 
			
		||||
						</DataTrigger>
 | 
			
		||||
					</Entry.Triggers>
 | 
			
		||||
                </Entry>
 | 
			
		||||
				<Label 
 | 
			
		||||
					Text="{Binding Password.Errors, Converter={StaticResource FirstValidationErrorConverter}"
 | 
			
		||||
					Style="{StaticResource ValidationErrorLabelStyle}" />
 | 
			
		||||
            </StackLayout>
 | 
			
		||||
            <!-- LOGIN BUTTON -->
 | 
			
		||||
            <Grid
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
using eShopOnContainers.Core.Helpers;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
@ -22,14 +21,16 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
            this.Content = null;
 | 
			
		||||
            this.Content = content;
 | 
			
		||||
 | 
			
		||||
            _animate = true;
 | 
			
		||||
            await AnimateIn();
 | 
			
		||||
 | 
			
		||||
            var vm = BindingContext as LoginViewModel;
 | 
			
		||||
 | 
			
		||||
            if(vm != null)
 | 
			
		||||
			var vm = BindingContext as LoginViewModel;
 | 
			
		||||
            if (vm != null)
 | 
			
		||||
            {
 | 
			
		||||
                vm.InvalidateMock();
 | 
			
		||||
 | 
			
		||||
				if (!vm.IsMock)
 | 
			
		||||
				{
 | 
			
		||||
					_animate = true;
 | 
			
		||||
					await AnimateIn();
 | 
			
		||||
				}
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -54,14 +55,13 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
            {
 | 
			
		||||
                while (_animate)
 | 
			
		||||
                {
 | 
			
		||||
                    await uiElement.ScaleTo(1.05, duration, Easing.SinInOut);
 | 
			
		||||
 | 
			
		||||
                    await Task.WhenAll(
 | 
			
		||||
                        uiElement.FadeTo(1, duration, Easing.SinInOut),
 | 
			
		||||
                        uiElement.LayoutTo(new Rectangle(new Point(0, 0), new Size(uiElement.Width, uiElement.Height))),
 | 
			
		||||
                        uiElement.FadeTo(.9, duration, Easing.SinInOut),
 | 
			
		||||
                        uiElement.ScaleTo(1.15, duration, Easing.SinInOut)
 | 
			
		||||
                    );
 | 
			
		||||
					await uiElement.ScaleTo(1.05, duration, Easing.SinInOut);
 | 
			
		||||
					await Task.WhenAll(
 | 
			
		||||
						uiElement.FadeTo(1, duration, Easing.SinInOut),
 | 
			
		||||
						uiElement.LayoutTo(new Rectangle(new Point(0, 0), new Size(uiElement.Width, uiElement.Height))),
 | 
			
		||||
						uiElement.FadeTo(.9, duration, Easing.SinInOut),
 | 
			
		||||
						uiElement.ScaleTo(1.15, duration, Easing.SinInOut)
 | 
			
		||||
					);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
            xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"
 | 
			
		||||
            BarBackgroundColor="{StaticResource DarkGreenColor}"
 | 
			
		||||
            BackgroundColor="{StaticResource BackgroundColor}"
 | 
			
		||||
            BarTextColor="{StaticResource WhiteColor}">
 | 
			
		||||
            BarTextColor="{StaticResource WhiteColor}"
 | 
			
		||||
			viewModelBase:ViewModelLocator.AutoWireViewModel="true">
 | 
			
		||||
    <TabbedPage.Title>
 | 
			
		||||
        <OnPlatform      
 | 
			
		||||
            x:TypeArguments="x:String"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
using eShopOnContainers.Core.ViewModels;
 | 
			
		||||
using eShopOnContainers.Core.ViewModels.Base;
 | 
			
		||||
using eShopOnContainers.ViewModels.Base;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
namespace eShopOnContainers.Core.Views
 | 
			
		||||
@ -16,7 +15,7 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
        {
 | 
			
		||||
            base.OnAppearing();
 | 
			
		||||
 | 
			
		||||
            MessagingCenter.Subscribe<MainViewModel, int>(this, MessengerKeys.ChangeTab, (sender, arg) =>
 | 
			
		||||
            MessagingCenter.Subscribe<MainViewModel, int>(this, MessageKeys.ChangeTab, (sender, arg) =>
 | 
			
		||||
            {
 | 
			
		||||
               switch(arg)
 | 
			
		||||
                {
 | 
			
		||||
@ -32,17 +31,9 @@ namespace eShopOnContainers.Core.Views
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            var homeViewModel = ViewModelLocator.Instance.Resolve<CatalogViewModel>();
 | 
			
		||||
            await homeViewModel.InitializeAsync(null);
 | 
			
		||||
            HomeView.BindingContext = homeViewModel;
 | 
			
		||||
 | 
			
		||||
            var basketViewModel = ViewModelLocator.Instance.Resolve<BasketViewModel>();
 | 
			
		||||
            await basketViewModel.InitializeAsync(null);
 | 
			
		||||
            BasketView.BindingContext = basketViewModel;
 | 
			
		||||
 | 
			
		||||
            var profileViewModel = ViewModelLocator.Instance.Resolve<ProfileViewModel>();
 | 
			
		||||
            await profileViewModel.InitializeAsync(null);
 | 
			
		||||
            ProfileView.BindingContext = profileViewModel;
 | 
			
		||||
			await ((CatalogViewModel)HomeView.BindingContext).InitializeAsync(null);
 | 
			
		||||
			await ((BasketViewModel)BasketView.BindingContext).InitializeAsync(null);
 | 
			
		||||
			await ((ProfileViewModel)ProfileView.BindingContext).InitializeAsync(null);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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" 
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.OrderDetailView"
 | 
			
		||||
			 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"   
 | 
			
		||||
             xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
             Title="{Binding Order.OrderNumber}">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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"       
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.ProfileView" 
 | 
			
		||||
             xmlns:views="clr-namespace:eShopOnContainers.Core.Views;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:templates="clr-namespace:eShopOnContainers.Core.Views.Templates;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"      
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
             Title="My profile">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,13 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<?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.SettingsView"   
 | 
			
		||||
             x:Class="eShopOnContainers.Core.Views.SettingsView"
 | 
			
		||||
			 xmlns:viewModelBase="clr-namespace:eShopOnContainers.Core.ViewModels.Base;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core"    
 | 
			
		||||
             xmlns:animations="clr-namespace:eShopOnContainers.Core.Animations;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:triggers="clr-namespace:eShopOnContainers.Core.Triggers;assembly=eShopOnContainers.Core"
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"   
 | 
			
		||||
             xmlns:behaviors="clr-namespace:eShopOnContainers.Core.Behaviors;assembly=eShopOnContainers.Core"
 | 
			
		||||
			 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
 | 
			
		||||
             Title="Settings">
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ResourceDictionary>
 | 
			
		||||
 | 
			
		||||
@ -58,9 +58,7 @@
 | 
			
		||||
    <Compile Include="Converters\ItemsToHeightConverter.cs" />
 | 
			
		||||
    <Compile Include="Converters\ItemTappedEventArgsConverter.cs" />
 | 
			
		||||
    <Compile Include="Converters\ToUpperConverter.cs" />
 | 
			
		||||
    <Compile Include="Effects\LineColorEffect.cs" />
 | 
			
		||||
    <Compile Include="Exceptions\ServiceAuthenticationException.cs" />
 | 
			
		||||
    <Compile Include="Extensions\AnimationExtension.cs" />
 | 
			
		||||
    <Compile Include="Extensions\ObservableExtension.cs" />
 | 
			
		||||
    <Compile Include="GlobalSettings.cs" />
 | 
			
		||||
    <Compile Include="Helpers\EasingHelper.cs" />
 | 
			
		||||
@ -111,7 +109,7 @@
 | 
			
		||||
    <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\MessageKeys.cs" />
 | 
			
		||||
    <Compile Include="ViewModels\Base\ViewModelBase.cs" />
 | 
			
		||||
    <Compile Include="ViewModels\Base\ViewModelLocator.cs" />
 | 
			
		||||
    <Compile Include="ViewModels\BasketViewModel.cs" />
 | 
			
		||||
@ -165,6 +163,9 @@
 | 
			
		||||
      <DependentUpon>ProductTemplate.xaml</DependentUpon>
 | 
			
		||||
    </Compile>
 | 
			
		||||
    <Compile Include="Converters\WebNavigatingEventArgsConverter.cs" />
 | 
			
		||||
    <Compile Include="Converters\FirstValidationErrorConverter.cs" />
 | 
			
		||||
    <Compile Include="Effects\EntryLineColorEffect.cs" />
 | 
			
		||||
    <Compile Include="Behaviors\LineColorBehavior.cs" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Include="app.config" />
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ using eShopOnContainers.Droid.Effects;
 | 
			
		||||
using Xamarin.Forms.Platform.Android;
 | 
			
		||||
using System;
 | 
			
		||||
using Android.Widget;
 | 
			
		||||
using eShopOnContainers.Core.Effects;
 | 
			
		||||
using eShopOnContainers.Core.Behaviors;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ namespace eShopOnContainers.Droid.Effects
 | 
			
		||||
 | 
			
		||||
        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName)
 | 
			
		||||
            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName)
 | 
			
		||||
            {
 | 
			
		||||
                UpdateLineColor();
 | 
			
		||||
            }
 | 
			
		||||
@ -46,7 +46,7 @@ namespace eShopOnContainers.Droid.Effects
 | 
			
		||||
            {
 | 
			
		||||
                if (control != null)
 | 
			
		||||
                {
 | 
			
		||||
                    control.Background.SetColorFilter(LineColorEffect.GetLineColor(Element).ToAndroid(), Android.Graphics.PorterDuff.Mode.SrcAtop);
 | 
			
		||||
                    control.Background.SetColorFilter(LineColorBehavior.GetLineColor(Element).ToAndroid(), Android.Graphics.PorterDuff.Mode.SrcAtop);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ using Xamarin.Forms;
 | 
			
		||||
using Xamarin.Forms.Platform.UWP;
 | 
			
		||||
using Windows.UI.Xaml.Controls;
 | 
			
		||||
using eShopOnContainers.Windows.Effects;
 | 
			
		||||
using eShopOnContainers.Core.Effects;
 | 
			
		||||
using eShopOnContainers.Core.Behaviors;
 | 
			
		||||
 | 
			
		||||
[assembly: ResolutionGroupName("eShopOnContainers")]
 | 
			
		||||
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]
 | 
			
		||||
@ -38,7 +38,7 @@ namespace eShopOnContainers.Windows.Effects
 | 
			
		||||
 | 
			
		||||
        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName)
 | 
			
		||||
            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName)
 | 
			
		||||
            {
 | 
			
		||||
                UpdateLineColor();
 | 
			
		||||
            }
 | 
			
		||||
@ -49,7 +49,7 @@ namespace eShopOnContainers.Windows.Effects
 | 
			
		||||
            if (control != null)
 | 
			
		||||
            {
 | 
			
		||||
                control.BorderThickness = new Xaml.Thickness(0, 0, 0, 1);
 | 
			
		||||
                var lineColor = XamarinFormColorToWindowsColor(LineColorEffect.GetLineColor(Element));
 | 
			
		||||
                var lineColor = XamarinFormColorToWindowsColor(LineColorBehavior.GetLineColor(Element));
 | 
			
		||||
                control.BorderBrush = new Media.SolidColorBrush(lineColor);
 | 
			
		||||
 | 
			
		||||
                var style = Xaml.Application.Current.Resources["FormTextBoxStyle"] as Xaml.Style;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
using CoreAnimation;
 | 
			
		||||
using CoreGraphics;
 | 
			
		||||
using eShopOnContainers.Core.Effects;
 | 
			
		||||
using eShopOnContainers.Core.Behaviors;
 | 
			
		||||
using eShopOnContainers.iOS.Effects;
 | 
			
		||||
using System;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
@ -39,7 +39,7 @@ namespace eShopOnContainers.iOS.Effects
 | 
			
		||||
        {
 | 
			
		||||
            base.OnElementPropertyChanged(args);
 | 
			
		||||
 | 
			
		||||
            if (args.PropertyName == LineColorEffect.LineColorProperty.PropertyName ||
 | 
			
		||||
            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName ||
 | 
			
		||||
                args.PropertyName == "Height")
 | 
			
		||||
            {
 | 
			
		||||
                Initialize();
 | 
			
		||||
@ -71,7 +71,7 @@ namespace eShopOnContainers.iOS.Effects
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lineLayer.Frame = new CGRect(0f, Control.Frame.Height - 1f, Control.Bounds.Width, 1f);
 | 
			
		||||
            lineLayer.BorderColor = LineColorEffect.GetLineColor(Element).ToCGColor();
 | 
			
		||||
            lineLayer.BorderColor = LineColorBehavior.GetLineColor(Element).ToCGColor();
 | 
			
		||||
            control.TintColor = control.TextColor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user