I have a page in an e-commerce app for the cart. I have my orders total price as a normal label on the xamarin view page outside of the data template in the xaml code as shown below. I have a button on the viewmodel page which handles the delete command of the products from the cart. I want the total order and the points label to update when a item is deleted from the cart.
Here is my code that I'm using
XAML
`<Button ImageSource="bin.png"
x:Name="btnDelete"
Command="{Binding Source={x:Reference cartCollectionView}, Path=BindingContext.CartsCommand}"
CommandParameter="{Binding .}"
Clicked="btnDelete_Clicked"
BackgroundColor="Transparent"
HorizontalOptions="EndAndExpand"/>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<StackLayout Orientation="Horizontal">
<Label Text="Order #:"
FontSize="20"
TextColor="Black"/>
<Label x:Name="txtOrderNumber"
FontSize="20"
TextColor="Black"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Total Woof Bits earned:" FontSize="Title" Margin="0,0,0,0" TextColor="Black"/>
<Label x:Name="txtPoints" Text="{Binding strPoints}" FontSize="Title" Margin="0,0,0,0" TextColor="Black"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Total Order:" FontSize="Title" TextColor="Black"/>
<Label x:Name="txtTotalOrder" Text="{Binding strTotalOrder}" FontSize="Title" TextColor="Black"/>
</StackLayout>`
View
`public CartPage(CartViewModel viewModels)
{
InitializeComponent();
BindingContext = viewModels;
BindingContext = new CartViewModel();
((CartViewModel)BindingContext).LoadCartsCommand.Execute(null);
((CartViewModel)BindingContext).LoadTotalsCommand.Execute(null);
txtOrderNumber.Text = SigninPage.strOrderNumber;
txtPoints.Text = CartViewModel.strPoints;
txtTotalOrder.Text = CartViewModel.strTotalOrder;
}
protected override void OnAppearing()
{
base.OnAppearing();
((CartViewModel)BindingContext).LoadCartsCommand.Execute(null);
((CartViewModel)BindingContext).LoadTotalsCommand.Execute(null);
txtPoints.Text = CartViewModel.strPoints;
txtTotalOrder.Text = CartViewModel.strTotalOrder;
}
private void Button_Clicked(object sender, EventArgs e)
{
((CartViewModel)BindingContext).PayCommand.Execute(null);
}
private void btnDelete_Clicked(object sender, EventArgs e)
{
((CartViewModel)BindingContext).LoadTotalsCommand.Execute(null);
txtPoints.Text = CartViewModel.strPoints;
txtTotalOrder.Text = CartViewModel.strTotalOrder;
DisplayAlert("Successful", "Item removed from Cart (▼´•̥ᴥ•̥`) ", "OK");
}`
ViewModel
`private ICommand _loadTotalsCommand;
public ICommand LoadTotalsCommand
{
get
{
if (_loadTotalsCommand == null)
{
_loadTotalsCommand = new Command(async () => await LoadTotals());
OnPropertyChanged();
}
return _loadTotalsCommand;
}
}
public async Task LoadTotals()
{
string sqlstring = "MySQL string";
MySqlConnection mysqlcon = new MySqlConnection(sqlstring);
MySqlCommand mysqlcom;
MySqlDataReader mdr;
mysqlcon.Open();
string selectquery = "SELECT ordernumber, quantity, price, sum(price * quantity) AS Total, sum(pointvalue) AS Total1 FROM cart WHERE ordernumber = '" + SigninPage.strOrderNumber + "' GROUP BY ordernumber;";
mysqlcom = new MySqlCommand(selectquery, mysqlcon);
mdr = mysqlcom.ExecuteReader();
while (mdr.Read())
if (mdr.FieldCount >= 1)
{
TotalOrder = mdr.GetDecimal(3);
Points = mdr.GetDecimal(4);
}
mysqlcon.Close();
strTotalOrder = "R" + Convert.ToString(TotalOrder);
strPoints = "🐾" + Convert.ToString(Points);
}
private ICommand _cartCommand;
public ICommand CartsCommand
{
get
{
if (_cartCommand == null)
{
_cartCommand = new Command<Cart>(async (cart) =>
{
await OnCartSelected(cart);
});
}
return _cartCommand;
}
}
public async Task OnCartSelected(Cart cart)
{
// Navigate to the ProductDetailsPage and pass the selected product as a parameter
string constring5 = "MySQL string";
MySqlConnection con5 = new MySqlConnection(constring5);
con5.Open();
MySqlTransaction transaction5 = con5.BeginTransaction();
using (MySqlCommand cmd5 = new MySqlCommand("DELETE FROM cart WHERE ordernumber = '" + strOrderNumber4 + "'", con5))
{
cmd5.Transaction = transaction5;
cmd5.ExecuteNonQuery();
transaction5.Commit();
con5.Close();
}
LoadTotalsCommand.Execute(null);
LoadCartsCommand.Execute(null);
}`
To make a conclusion,
1. Use a proper mvvm way. You may refer to From Data Bindings to MVVM. Bind to a property in ViewModel and raise PropertyChanged event :
private string _strPoints;
public string strPoints
{
get
{
return _strPoints;
}
set
{
_strPoints = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(strPoints)));
}
}
When strPoints
value changed, the UI would refresh.
2. For TabbedPage passing arguments into constructor, you may refer to this: Passing Arguments in XAML
<NavigationPage Title="Cart" IconImageSource="cart.png">
<x:Arguments>
<local:CartPage Title="Cart">
<x:Arguments>
<viewModels:CartViewModel/>
</x:Arguments>
</local:CartPage>
</x:Arguments>
</NavigationPage>
That generate a CartViewModel instance and pass it to the Constructor.
So for CartPage.cs, don't have to create any new CartViewModel instance any more.
CartViewModel ViewModel;
public CartPage(CartViewModel viewModels)
{
InitializeComponent();
BindingContext = viewModels;
ViewModel = viewModels;
}
3. A way to change the color of RadioButton for Android is to use Custom Renderer
Step1.Create your own custom RadioButton in shared project:
public class MyRadioButton : RadioButton
{
public MyRadioButton()
{
}
}
Step2.Then in YourProject.Android folder create MyRadioButtonRenderer.cs
[assembly: ExportRenderer(typeof(MyRadioButton), typeof(MyRadioButtonRenderer))]
namespace ViewPageLabelNotRefreshing76512008.Droid
{
public class MyRadioButtonRenderer : RadioButtonRenderer
{
public MyRadioButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<RadioButton> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.ButtonTintList = ColorStateList.ValueOf(Android.Graphics.Color.ForestGreen);
}
}
}
}
Step3.Consume it in xaml,
<local:MyRadioButton x:Name="Delivery" Content="Delivery" CheckedChanged="RadioButton_CheckedChanged"/>
Hope it helps!