I am making a client application for a product store. The shopping cart is located on the server and the data is transferred there using requests to the server. The product basket is an ObservableCollection
. The view also shows the total price generated in the ViewModel
constructor. I implemented the command to remove an item from the observablecollection, and also put in the command to subtract the cost of the deleted item from the total amount parameter. The deleted item disappears from the list in the view, but the displayed amount remains the same.
XAML Code:
<StackLayout>
<CollectionView ItemsSource="{Binding ProductsInBasket}" VerticalOptions="FillAndExpand" x:Name="clv_basket">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="dataModel:DTOProductAndQuantity">
<Frame Padding="2" Margin="25,10,25,0" HasShadow="False" BorderColor="LightGray" CornerRadius="15">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Frame Grid.Column="0" HasShadow="False" CornerRadius="15" WidthRequest="200" HeightRequest="200" HorizontalOptions="Center">
<Image Grid.Column="0" HeightRequest="200" WidthRequest="200" Margin="0,0,0,0" Source="{Binding product.Photo, Mode=OneWay, Converter={StaticResource ByteToImage}}"/>
</Frame>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Text="{Binding product.NameProduct}" FontSize="19" TextColor="#006064" VerticalOptions="Center" Grid.Row="0"/>
<Label Text="{Binding product.Category}" FontSize="18" TextColor="#006064" VerticalOptions="Center" Grid.Row="1"/>
<Label Text="{Binding product.Cost, StringFormat='cost per piece: {0} rub.'}" FontSize="18" TextColor="#006064" VerticalOptions="Center" Grid.Row="2"/>
</Grid>
<Grid Grid.Column="2">
<StackLayout VerticalOptions="End">
<Label Text="{Binding quantityInBusket}" FontSize="17" HorizontalOptions="Center" TextColor="BlueViolet"/>
<Stepper Maximum="10" HorizontalOptions="Center" Increment="1" Value="{Binding quantityInBusket}"/>
</StackLayout>
<Button VerticalOptions="Start" HorizontalOptions="End" Command="{Binding Path=BindingContext.DeleteProductCommand, Source={x:Reference clv_basket}}" CommandParameter="{Binding}"/>
</Grid>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Frame CornerRadius="2">
<StackLayout>
<Label Text="{Binding Sum, StringFormat='Sum: {0} rub.'}" HorizontalOptions="Center" FontSize="20" TextColor="Black"/>
</StackLayout>
</Frame>
</StackLayout>
ViewModel Code:
class BusketViewModel
{
#region Fields
private double sum;
private ObservableCollection<DTOProductAndQuantity> productsInBasket;
private ObservableCollection<DTOProductAndQuantity> productsFromHttp;
HttpClient httpClient = new HttpClient();
private Command<object> deleteProductCommand;
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Constructor
public BusketViewModel()
{
productsFromHttp = httpClient.GetFromJsonAsync<ObservableCollection<DTOProductAndQuantity>>("http://10.0.2.2:5125/api/Busket").Result;
deleteProductCommand = new Command<object>(DeleteProduct);
ProductsInBasket = new ObservableCollection<DTOProductAndQuantity>(productsFromHttp);
foreach (var i in ProductsInBasket)
Sum += i.product.Cost * i.quantityInBusket;
}
private void DeleteProduct(object obj)
{
Sum -= (obj as DTOProductAndQuantity).product.Cost * (obj as DTOProductAndQuantity).quantityInBusket;
ProductsInBasket.Remove(obj as DTOProductAndQuantity);
}
#endregion
#region Properties
public ObservableCollection<DTOProductAndQuantity> ProductsInBasket
{
get { return productsInBasket; }
set
{
if (productsInBasket != value)
{
productsInBasket = value;
NotifyPropertyChanged();
}
}
}
public Command<object> DeleteProductCommand
{
get { return deleteProductCommand; }
set { deleteProductCommand = value; }
}
public double Sum
{
get { return sum; }
set
{
if (sum != value)
{
sum = value;
NotifyPropertyChanged();
}
}
}
#endregion
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}