locked
How can i create a custom control to add quantity of any product for sales App RRS feed

  • Question

  • User355323 posted

    Hi all, How can i create a custom control for add items with quantity in listview, I've attached a sample image.

    Thanks

    Friday, June 5, 2020 8:48 AM

Answers

  • User380187 posted

    Hi @Ajay87 , using the Model-View-ViewModel (MVVM) architectural pattern to achieve that . Binding ViewModel for ListViewand add INotifyPropertyChanged to update View when running project .

    Such as creare a Custom ContentView named QualityView ,the Xaml code as follow :

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 mc:Ignorable="d"
                 x:Class="AppEntryTest.QualityView">
      <ContentView.Content>
            <StackLayout>
                <Frame BorderColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                    <StackLayout Orientation="Horizontal">
                        <ImageButton Source="minus.png"
                                     BackgroundColor="Transparent"
                                     Command="{Binding MinusCommand}"
                                     WidthRequest="60" 
                                     VerticalOptions="Center" />
                        <Label Text="{Binding Number}"
                               TextColor="Green"
                               HorizontalTextAlignment="Center"
                               WidthRequest="60"
                               VerticalOptions="Center" />
                        <ImageButton Source="plus.png"
                                     BackgroundColor="Transparent"
                                     Command="{Binding PlusCommand}" 
                                     WidthRequest="60"
                                     VerticalOptions="Center" />
                    </StackLayout>
                </Frame>
            </StackLayout>
      </ContentView.Content>
    </ContentView>
    

    Used in ListView :

    <ListView x:Name="listViewCities"
                ItemTapped="ListViewCities_ItemTapped"
                RowHeight="80">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" VerticalOptions="Center">
                        <Label Text=" View with other info " VerticalOptions="Center"/>
                        <appentrytest:QualityView />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    Then we need a model to bind , named QualityViewModel here :

    public class QualityViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public ICommand PlusCommand { private set; get; }
        public ICommand MinusCommand { private set; get; }
        private int number;
    
        public int Number
        {
            set
            {
                if (number != value)
                {
                    number = value;
                    OnPropertyChanged("Number");
                }
            }
            get
            {
                return number;
            }
        }
    
        public QualityViewModel()
        {
            PlusCommand = new Command(
            execute: () =>
            {
                number++;
                OnPropertyChanged("Number");
                RefreshCanExecutes();
            });
    
            MinusCommand = new Command(
            execute: () =>
            {
                number--;
                OnPropertyChanged("Number");
                RefreshCanExecutes();
            });
        }
    
        private void RefreshCanExecutes()
        {
            (PlusCommand as Command).ChangeCanExecute();
            (MinusCommand as Command).ChangeCanExecute();
        }
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    Last used in ContentPage:

    public List<QualityViewModel> qualityViewModels { set; get; }
    public PageThree()
    {
        InitializeComponent();
    
        qualityViewModels = new List<QualityViewModel>();
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
    
        listViewCities.ItemsSource = qualityViewModels;
    }
    

    The effect :

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, June 8, 2020 1:51 AM
  • User380187 posted

    Hi @Ajay87 ,you also can create a custom ContentView(CustomDialog) for this toast :

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 mc:Ignorable="d"
                 x:Class="AppEntryTest.Controls.CustomDialog">
      <ContentView.Content>
          <StackLayout Padding="120" >
                <Frame BackgroundColor="LightBlue" BorderColor="LightBlue" HeightRequest="25"  CornerRadius="100">
                    <StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="Center">
                        <Image Source="knifeandfork.png"/>
                        <Label Text="MENU" FontSize="Large" TextColor="White"/>
                    </StackLayout>
                </Frame>
          </StackLayout>
      </ContentView.Content>
    </ContentView>
    

    Used in ContentPage :

    <controls:CustomDialog x:Name="CustomeDialog" IsVisible="false"/>
    <Button Text="show" Clicked="Button_Clicked"/>
    

    Here you can used AbsoluteLayout to modfiy the position of CustomDialog .ContentPage.cs code as follow :

    private void Button_Clicked(object sender, EventArgs e)
    {
        CustomeDialog.IsVisible = true;
        Device.StartTimer(new TimeSpan(0, 0, 3), () =>
        {
    
            // do something every 60 seconds
            Device.BeginInvokeOnMainThread(() =>
            {
                // interact with UI elements
                CustomeDialog.IsVisible = false;
            });
            return false; // runs again, or false to stop
        });
    }
    

    The effect :

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, June 18, 2020 9:12 AM

All replies

  • User380187 posted

    Hi @Ajay87 , using the Model-View-ViewModel (MVVM) architectural pattern to achieve that . Binding ViewModel for ListViewand add INotifyPropertyChanged to update View when running project .

    Such as creare a Custom ContentView named QualityView ,the Xaml code as follow :

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 mc:Ignorable="d"
                 x:Class="AppEntryTest.QualityView">
      <ContentView.Content>
            <StackLayout>
                <Frame BorderColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                    <StackLayout Orientation="Horizontal">
                        <ImageButton Source="minus.png"
                                     BackgroundColor="Transparent"
                                     Command="{Binding MinusCommand}"
                                     WidthRequest="60" 
                                     VerticalOptions="Center" />
                        <Label Text="{Binding Number}"
                               TextColor="Green"
                               HorizontalTextAlignment="Center"
                               WidthRequest="60"
                               VerticalOptions="Center" />
                        <ImageButton Source="plus.png"
                                     BackgroundColor="Transparent"
                                     Command="{Binding PlusCommand}" 
                                     WidthRequest="60"
                                     VerticalOptions="Center" />
                    </StackLayout>
                </Frame>
            </StackLayout>
      </ContentView.Content>
    </ContentView>
    

    Used in ListView :

    <ListView x:Name="listViewCities"
                ItemTapped="ListViewCities_ItemTapped"
                RowHeight="80">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" VerticalOptions="Center">
                        <Label Text=" View with other info " VerticalOptions="Center"/>
                        <appentrytest:QualityView />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    Then we need a model to bind , named QualityViewModel here :

    public class QualityViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public ICommand PlusCommand { private set; get; }
        public ICommand MinusCommand { private set; get; }
        private int number;
    
        public int Number
        {
            set
            {
                if (number != value)
                {
                    number = value;
                    OnPropertyChanged("Number");
                }
            }
            get
            {
                return number;
            }
        }
    
        public QualityViewModel()
        {
            PlusCommand = new Command(
            execute: () =>
            {
                number++;
                OnPropertyChanged("Number");
                RefreshCanExecutes();
            });
    
            MinusCommand = new Command(
            execute: () =>
            {
                number--;
                OnPropertyChanged("Number");
                RefreshCanExecutes();
            });
        }
    
        private void RefreshCanExecutes()
        {
            (PlusCommand as Command).ChangeCanExecute();
            (MinusCommand as Command).ChangeCanExecute();
        }
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    Last used in ContentPage:

    public List<QualityViewModel> qualityViewModels { set; get; }
    public PageThree()
    {
        InitializeComponent();
    
        qualityViewModels = new List<QualityViewModel>();
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
        qualityViewModels.Add(new QualityViewModel() { Number = 0 });
    
        listViewCities.ItemsSource = qualityViewModels;
    }
    

    The effect :

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, June 8, 2020 1:51 AM
  • User380187 posted

    Hi @Ajay87 , I have updated the comment , you can have a look when you have time :-)

    More info refer to here : https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

    Wednesday, June 17, 2020 1:26 AM
  • User355323 posted

    Hi @JuniorJiang Thanks for your response, Your answer is very helpful but i've already created that control with the help of this https://forums.xamarin.com/discussion/147114/custom-stepper-with-2-buttons-and-entry

    Thanks

    Wednesday, June 17, 2020 4:54 AM
  • User355323 posted

    @JuniorJiang Hi jiang, i need to create popups like toast(Menu & Cart details) any idea about this. I've attached an image.

    Thanks

    Thursday, June 18, 2020 7:52 AM
  • User380187 posted

    Hi @Ajay87 ,you also can create a custom ContentView(CustomDialog) for this toast :

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 mc:Ignorable="d"
                 x:Class="AppEntryTest.Controls.CustomDialog">
      <ContentView.Content>
          <StackLayout Padding="120" >
                <Frame BackgroundColor="LightBlue" BorderColor="LightBlue" HeightRequest="25"  CornerRadius="100">
                    <StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="Center">
                        <Image Source="knifeandfork.png"/>
                        <Label Text="MENU" FontSize="Large" TextColor="White"/>
                    </StackLayout>
                </Frame>
          </StackLayout>
      </ContentView.Content>
    </ContentView>
    

    Used in ContentPage :

    <controls:CustomDialog x:Name="CustomeDialog" IsVisible="false"/>
    <Button Text="show" Clicked="Button_Clicked"/>
    

    Here you can used AbsoluteLayout to modfiy the position of CustomDialog .ContentPage.cs code as follow :

    private void Button_Clicked(object sender, EventArgs e)
    {
        CustomeDialog.IsVisible = true;
        Device.StartTimer(new TimeSpan(0, 0, 3), () =>
        {
    
            // do something every 60 seconds
            Device.BeginInvokeOnMainThread(() =>
            {
                // interact with UI elements
                CustomeDialog.IsVisible = false;
            });
            return false; // runs again, or false to stop
        });
    }
    

    The effect :

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, June 18, 2020 9:12 AM
  • User355323 posted

    Thanks @JuniorJiang Will try it.

    Thursday, June 18, 2020 9:23 AM