Learn Technologies
Xamarin Forms-E-Commerce Application 3

Xamarin Forms – E-commerce Application – Add to cart button(part 3)

In this new tutorial of Xamarin Forms E-commerce application. We’ll see together how to add to cart (Basket) button in the navigation bar.
If this is the first experience with Xamarin Forms, I invite you to check my first post Xamarin Forms – Prism.

You can also see, the Part 1 and Part 2 of this tutorial.

The code is available on GitHub.

So, to make this Add to cart button, we gonna using something called userControl.

Card Button (Basket)

First of all, let’s begin by adding a custom navigation which contains the title, the card button and the number of products available in basket.
So this code will be used in several pages like ProductDetails and ProductsPage. To avoid code duplication, we’ll create a reusable UserControl called BasketHeader under Views/UserControls.

So your, code will be like:

<?xml version="1.0" encoding="utf-8" ?>
<Grid  xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
  x:Class="Shopping.Views.UserControls.BasketHeaderUserControl"
        ColumnDefinitions="*,60"
       x:Name="BasketHeader">
    <Label Text="{Binding Title}"
                   TextColor="White"
                   FontSize="20"
                   VerticalTextAlignment="Center"/>
    <Frame Grid.Column="1"
                   Margin="0"
                   Padding="5"
                   BorderColor="Green"
                   HasShadow="True"
                   CornerRadius="50"
                   WidthRequest="40"
                   BackgroundColor="White"
                   HorizontalOptions="Center">
        <ImageButton WidthRequest="40"
                             HeightRequest="40"
                             Padding="5"
                             Source="add_to_basket.png"
                             BackgroundColor="Transparent"
                             VerticalOptions="Center"
                             HorizontalOptions="Center"/>
    </Frame>
    <Frame Grid.Column="1"
                   WidthRequest="20"
                   VerticalOptions="Center"
                   HorizontalOptions="Center"
                   CornerRadius="50"
                   BackgroundColor="Red"
                   Margin="30,-30,0,0"
                    HasShadow="true"
                   BorderColor="Black"
                   Padding="1">
        <Label Text="{Binding ProductCount}"
                       TextColor="White"
                       HorizontalTextAlignment="Center"
                       VerticalTextAlignment="Center"/>
    </Frame>
    <Grid.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding GoToBasketCommand}"
                              NumberOfTapsRequired="1"/>
    </Grid.GestureRecognizers>
</Grid>

After that, we have to add 3 bindable properties Title, ProductCount and GoToBasketCommand in BasketHeaderUserControl.cs .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Shopping.Views.UserControls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class BasketHeaderUserControl : Grid
    {
        public static readonly BindableProperty TitleProperty =
            BindableProperty.Create("Title", typeof(string), typeof(BasketHeaderUserControl));

        public static readonly BindableProperty ProductCountProperty =
          BindableProperty.Create("ProductCount", typeof(int), typeof(BasketHeaderUserControl));


        public static readonly BindableProperty GoToBasketCommandProperty =
            BindableProperty.Create("GoToBasketCommand", typeof(ICommand), typeof(BasketHeaderUserControl));

        public int ProductCount
        {
            get => (int)GetValue(ProductCountProperty);
            set => SetValue(ProductCountProperty, value);
        }


        public string Title
        {
            get => (string)GetValue(TitleProperty) ;
            set => SetValue(TitleProperty, value);
        }

        public ICommand GoToBasketCommand
        {
            get => (ICommand)GetValue(GoToBasketCommandProperty);
            set => SetValue(GoToBasketCommandProperty, value);
        }

        public BasketHeaderUserControl()
        {
            InitializeComponent();
        }
    }
}

Finally, use the created user Control in the targets pages (ProductDetailsPage and ProductsPage).

 <NavigationPage.TitleView>
        <UserCtrls:BasketHeaderUserControl Title="{Binding Title}"
                                           ProductCount="{Binding Source={x:Reference ProductDetails}, Path=BindingContext.ProductCount}"
                                           GoToBasketCommand="{Binding Source={x:Reference ProductDetails}, Path=BindingContext.GoToBasketCommand}"
                                          />
    </NavigationPage.TitleView>

In the ProductDetailsViewModel, add the command AddProductToBasketCommand. When user tap the buy button, we add the product to the basket. The products list will be declared in the ViewModelBase to be used by all the others ViewModels.

MessagingCenter 

MessagingCenter  implements the publish-subscribe pattern. This mechanism allows also, publishers and subscribers to communicate without having a reference to each other. You can see the official documentation on Microsoft site web.

Let’s begin by send method which takes 3 parameters. We find the sender, the message and the data to send.

You code looks like this:

public ICommand AddProductToBasketCommand { get; set; }
public ProductDetailsPageViewModel(INavigationService navigationService, IProductsService productsService)
            : base(navigationService)
{
            this.productsService = productsService;
            IncreaseQuantityCommand = new DelegateCommand(IncreaseQuantity);
            DecreaseQuantityCommand = new DelegateCommand(DecreaseQuantity);
            AddProductToBasketCommand = new DelegateCommand(AddProductToBasket);
}

private void AddProductToBasket()
{
    MessagingCenter.Send("UpdateBasket", "Add product", productModel);
}

In the other side, where we’ll manage the products list object, you have to subscribe to this message. when the user adds a product to the cart, the event subscriber is triggered and in it, you will manage the addition of the product to the existant list.

The most appropriate place to register for the product add event is ViewModelBase. Let’s begin by adding new method called SubscribeToEvents.

private void SubscribeToEvents()
{
     MessagingCenter.Unsubscribe<string, ProductModel>("UpdateBasket", "Add product");
     MessagingCenter.Subscribe<string, ProductModel>("UpdateBasket", "Add product", (sender, args) => {
              
     List<ProductModel> productsList = new List<ProductModel>();
     var jsonProductsList = Preferences.Get("BasketList", null);
     if (!string.IsNullOrEmpty(jsonProductsList))
     {
        productsList = JsonConvert.DeserializeObject<List<ProductModel>>(Preferences.Get("BasketList", null));
     }
     productsList.Add(args);
     ProductCount = productsList.Count;
     Preferences.Set("BasketList", JsonConvert.SerializeObject(productsList));
     });
}

In order to avoid duplication of event registrations, and first of all, you must unsubscribe from the event by calling Unsubscribe method.

After that, you need to save your product list in temporary place. We gonne use Xamarin Essentials to save the list in the application cache. Before saving the product, you retrieve the existant list and add the new product.

Finally, save the new list again in the temporary place by calling Preferences.Set(“BasketList”,….)

Obviously, we can make this operation in ProductsService, but this tutorial is only for demo propose.

Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter or GitHub to be notified when I post new content.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x