xamarin 表单 - 选择器在页面加载时不显示任何值
xamarin forms - picker not displaying any value on page load
将 MVVM 与 xamarin 表单结合使用。 ProductPage 包含产品的 ListView。每个产品都有一个选择器。
用户 select 想要购买的商品的数量。用户点击购物车图像。
ShoppingCartPage 加载显示用户已 select 编辑的项目,但选择器为空白。我希望选择器显示从 productaPage 中选择的数量
我已经逐步完成了后面的代码和
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value)
在 ShoppingCartPage 的 OnAppearing() 上存储了正确的数量值,但我不明白为什么选择器没有显示正确的值。
已尝试以下所有建议:
https://forums.xamarin.com/discussion/153788/set-a-picker-selecteditem-on-page-startup
Item to Display for Picker don't show up on load
但仍然无法正常工作有人知道我做错了什么吗?
感谢任何建议
public class ProductModel : INotifyPropertyChanged
{
//Event
public event PropertyChangedEventHandler PropertyChanged;
//Fields
//[PrimaryKey, AutoIncrement]
private int _ProductId;
private string _ProductName;
private string _Quantity;
private string _Description;
private string _Image;
private decimal _Price;
private decimal _SubTotalForItem;
private string _Genre;
public ObservableCollection<Quantity> _ListQuantites;
//Constructor
public ProductModel()
{
//Subscription
this.PropertyChanged += OnPropertyChanged;
}
[PrimaryKey, AutoIncrement]
public int ProductId
{
get { return _ProductId; }
set
{
if (_ProductId == value) return;
_ProductId = value;
OnPropertyChanged();
}
}
//Properties
public string Quantity
{
get
{
return _Quantity;
}
set
{
_Quantity = value;
OnPropertyChanged();
}
}
public ObservableCollection<Quantity> ListQuantites
{
get
{
return _ListQuantites;
}
set
{
_ListQuantites = value;
OnPropertyChanged();
}
}
private Quantity _selectedQuantity;
public Quantity SelectedQuantity
{
get
{
return _selectedQuantity;
}
set
{
if (value == null)
{
_selectedQuantity = _selectedQuantity;
}
else
{
_selectedQuantity = value;
OnPropertyChanged();
}
}
}
[MaxLength(50)]
public string Description
{
get
{
return _Description;
}
set
{
_Description = value;
OnPropertyChanged();
}
}
public string Image
{
get
{
return _Image;
}
set
{
_Image = value;
OnPropertyChanged();
}
}
public decimal Price
{
get
{
return _Price;
}
set
{
_Price = value;
OnPropertyChanged();
}
}
public decimal SubTotalForItem
{
get
{
return _SubTotalForItem;
}
set
{
_SubTotalForItem = value;
OnPropertyChanged();
}
}
public string Genre
{
get
{
return _Genre;
}
set
{
_Genre = value;
OnPropertyChanged();
}
}
public string ProductName
{
get { return _ProductName; }
set
{
_ProductName = value;
OnPropertyChanged();
}
}
//OnPropertyChanged
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SelectedQuantity))
{
//test quantity amount
}
}
// [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
----------------
public class Quantity
{
public int Key { get; set; }
public string Value { get; set; }
}
----------------
public class PickerService
{
public static ObservableCollection<Quantity> GetQuantitiesForProductPage()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="0"},
new Quantity() {Key=2, Value="1"},
new Quantity() {Key=3, Value="2"},
new Quantity() {Key=4, Value="3"},
new Quantity() {Key=5, Value="4"},
new Quantity() {Key=6, Value="5"},
new Quantity() {Key=7, Value="6"},
new Quantity() {Key=8, Value="7"},
new Quantity() {Key=9, Value="8"},
new Quantity() {Key=10, Value="9"},
new Quantity() {Key=11, Value="10"}
};
return quantities;
}
public static ObservableCollection<Quantity> GetQuantitiesForShoppingcart()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="1"},
new Quantity() {Key=2, Value="2"},
new Quantity() {Key=3, Value="3"},
new Quantity() {Key=4, Value="4"},
new Quantity() {Key=5, Value="5"},
new Quantity() {Key=6, Value="6"},
new Quantity() {Key=7, Value="7"},
new Quantity() {Key=8, Value="8"},
new Quantity() {Key=9, Value="9"},
new Quantity() {Key=10, Value="10"},
};
return quantities;
}
}
--------------
public class ShoppingCartViewModel //: INotifyPropertyChanged
{
private ObservableCollection<ProductModel> _shoppingCartList;
public ObservableCollection<ProductModel> ShoppingCartList
{
get
{
return _shoppingCartList;
}
set
{
if (_shoppingCartList == value) return;
_shoppingCartList = value;
}
}
public ShoppingCartViewModel()
{
ShoppingCartList = new ObservableCollection<ProductModel>();
}
}
----------------
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ShoppingCartPage : ContentPage
{
ShoppingCartViewModel ShoppingCartViewModel = new ShoppingCartViewModel();
public decimal TotalForAllItems;
public ObservableCollection<Quantity> List_Quantites { get; set; }
public ShoppingCartPage()
{
InitializeComponent();
BindingContext = ShoppingCartViewModel;
}
public int CalculateQuantityOfItemsInShoppingCart()
{
int quantityOfProducts = 0;
if (ShoppingCartViewModel.ShoppingCartList != null)
{
foreach (var product in ShoppingCartViewModel.ShoppingCartList)
{
if (product.SelectedQuantity != null)
{
quantityOfProducts += Convert.ToInt32(product.SelectedQuantity.Value);
}
}
}
return quantityOfProducts;
}
protected override void OnDisappearing()
{
App.globalShoppingCartOC = ShoppingCartViewModel.ShoppingCartList;
}
protected override void OnAppearing()
{
base.OnAppearing();
TotalForAllItems = 0.00M;
List_Quantites = PickerService.GetQuantitiesForShoppingcart();
ShoppingCartViewModel.ShoppingCartList.Clear();
if (App.globalShoppingCartOC != null)
{
foreach (ProductModel Model in App.globalShoppingCartOC)
{
if (Model.SelectedQuantity != null)
{
var _quantity = Convert.ToDecimal(Model.SelectedQuantity.Value);
if (_quantity > 0)
{
Model.SubTotalForItem = _quantity * Model.Price;
//this line resets Model.SelectedQuantity to 0, so need to re-populate with tempQuantity value
Quantity tempQuantity = Model.SelectedQuantity;
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
ShoppingCartViewModel.ShoppingCartList.Add(Model);
TotalForAllItems += Model.SubTotalForItem;
}
}
}
SubTotalForAllItems.Text = TotalForAllItems.ToString();
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
protected async void SI_Invoked(object sender, EventArgs e)
{
var si = sender as SwipeItem;
var productToRemove = si.CommandParameter as ProductModel;
var action = await DisplayAlert("Are you sure you want to remove ", productToRemove.ProductName + ".", "Yes", "No");
if (action)
{
ShoppingCartViewModel.ShoppingCartList.Remove(productToRemove);
Quantity tempQuantity = productToRemove.SelectedQuantity;
decimal tempQuantityValue = Convert.ToDecimal(tempQuantity.Value);
decimal subtotalToRemove = productToRemove.Price * tempQuantityValue;
TotalForAllItems -= subtotalToRemove;
SubTotalForAllItems.Text = TotalForAllItems.ToString();
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
}
public void SCQuantityAndSubtotalUpdated(object sender, EventArgs e)
{
TotalForAllItems = 0.00M;
if (ShoppingCartViewModel.ShoppingCartList != null)
{
foreach (ProductModel Model in ShoppingCartViewModel.ShoppingCartList)
{
var _quantity = Convert.ToDecimal(Model.SelectedQuantity.Value);
if (_quantity > 0)
{
Model.SubTotalForItem = _quantity * Model.Price;
TotalForAllItems += Model.SubTotalForItem;
}
}
SubTotalForAllItems.Text = TotalForAllItems.ToString();
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
private void PlaceOrder_BtnClicked(object sender, EventArgs e)
{
}
}
-------------------------
<ContentPage.ToolbarItems>
<ToolbarItem Name="shoppingCartImg" Icon="shopping_cart.png" Priority="0" Order="Primary"/>
<ToolbarItem x:Name="NoItemsInShoppingCart" Priority="0" Order="Primary"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView ItemsSource="{Binding ShoppingCartList}" IsVisible="True" VerticalOptions="FillAndExpand" HasUnevenRows="True">
<ListView.Header>
<Button Text="Place Order" Clicked="PlaceOrder_BtnClicked"/>
</ListView.Header>
<ListView.Footer>
<Label x:Name="SubTotalForAllItems" HorizontalTextAlignment="End" VerticalTextAlignment="Start" Margin="20,20" FontAttributes="Bold"/>
</ListView.Footer>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems Mode="Reveal">
<SwipeItem Text="Details" IconImageSource="xamarin_logo.png" CommandParameter="{Binding .}" BackgroundColor="LightBlue" Invoked="SI_Invoked">
</SwipeItem>
</SwipeItems>
</SwipeView.LeftItems>
<!--Content of Swipe View -->
<StackLayout BackgroundColor="Green" HorizontalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding ProductId}" VerticalOptions="End" IsVisible="False"/>
<controls:CircleImage Grid.Column="1" Grid.Row="0" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
<Label Grid.Column="2" Grid.Row="0" Text="{Binding ProductName}" VerticalOptions="Start"/>
<Label Grid.Column="2" Grid.Row="1" Text="{Binding Description}" VerticalOptions="End"/>
<Label Grid.Column="3" Grid.Row="0" VerticalOptions="Start" Text="{Binding SubTotalForItem, StringFormat='£{0:0.00}'}"/>
<Picker x:Name="scPicker" ItemsSource="{Binding ListQuantites, Mode=TwoWay}" SelectedItem="{Binding SelectedQuantity, Mode=TwoWay}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="SCQuantityAndSubtotalUpdated"/>
</Grid>
</StackLayout>
</SwipeView>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
-------------------------
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductPage : ContentPage
{
public ProductPageViewModel productPage_ViewModal;
MainPage RootPage { get => Application.Current.MainPage as MainPage; }
public ProductPage()
{
InitializeComponent();
productPage_ViewModal = new ProductPageViewModel();
BindingContext = productPage_ViewModal;
}
protected override void OnDisappearing()
{
App.globalShoppingCartOC = productPage_ViewModal.WineList;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (App.globalShoppingCartOC != null)
{
//First need to check shoppingCart list for product, if it has been removed in SC,
//then set quantity to 0
foreach (var product in productPage_ViewModal.WineList)
{
var doesProductExistInShoppingCart = App.globalShoppingCartOC.Where(x => x.ProductId == product.ProductId).FirstOrDefault();
if(doesProductExistInShoppingCart == null)
{
if (productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity != null)
{
Quantity tempQuantity = new Quantity() { Key = 1, Value = "0" };
product.SelectedQuantity = productPage_ViewModal.List_Quantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
product.ListQuantites = PickerService.GetQuantitiesForProductPage();
// productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity.Value = "0";
}
}
}
//Can then update correct quantity for other products still in SC list
foreach (var product in App.globalShoppingCartOC)
{
if (productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity != null)
{
Quantity tempQuantity = product.SelectedQuantity;
product.SelectedQuantity = productPage_ViewModal.List_Quantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
product.ListQuantites = PickerService.GetQuantitiesForProductPage();
//productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity.Value = product.SelectedQuantity.Value;
}
}
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
private async void ShoppingCartClicked(object sender, EventArgs e)
{
MenuPage tempMenu = new MenuPage();
int IdOfMenuClicked = tempMenu.GetIdForNavigationMenu("Shopping Cart");
await RootPage.NavigateFromMenu(IdOfMenuClicked);
}
public void QuantityChanged(object sender, EventArgs e)
{
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
public int CalculateQuantityOfItemsInShoppingCart()
{
int quantityOfProducts = 0;
if (productPage_ViewModal.WineList != null)
{
foreach (var product in productPage_ViewModal.WineList)
{
if (product.SelectedQuantity != null)
{
quantityOfProducts += Convert.ToInt32(product.SelectedQuantity.Value);
}
}
}
return quantityOfProducts;
}
}
-------------------------
Title="ProductPage">
<ContentPage.ToolbarItems>
<ToolbarItem Name="shoppingCartImg" Icon="shopping_cart.png" Priority="0" Order="Primary" Activated="ShoppingCartClicked"/>
<ToolbarItem x:Name="NoItemsInShoppingCart" Priority="0" Order="Primary" Activated="ShoppingCartClicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView IsVisible="True" VerticalOptions="FillAndExpand" HasUnevenRows="True" ItemsSource="{Binding WineList}"> <!--HeightRequest="1500"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="Green" HorizontalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding ProductId}" VerticalOptions="End" IsVisible="False"/>
<controls:CircleImage Grid.Column="1" Grid.Row="0" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
<Label Grid.Column="2" Grid.Row="0" Text="{Binding ProductName}" VerticalOptions="Start"/>
<Label Grid.Column="2" Grid.Row="1" Text="{Binding Description}" VerticalOptions="End"/>
<Label Grid.Column="3" Grid.Row="0" VerticalOptions="Start" Text="{Binding Price, StringFormat='£{0:0.00}'}"/>
<Picker x:Name="productPicker" ItemsSource="{Binding ListQuantites}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="QuantityChanged" SelectedItem ="{Binding SelectedQuantity}"/>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
----------------------------------------------
public class ProductPageViewModel : BindableObject, INotifyPropertyChanged
{
public ObservableCollection<ProductModel> WineList { get; set; }
public ObservableCollection<Quantity> List_Quantites { get; set; }
public ProductPageViewModel()
{
List_Quantites = PickerService.GetQuantitiesForProductPage();//.OrderBy(c => c.Value).ToList();
WineList = new ObservableCollection<ProductModel>();
WineList.Add(new ProductModel { ProductId = 1, ProductName = "Wine 1", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 10.00M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 2, ProductName = "Wine 2", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 10.00M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 3, ProductName = "Wine 3", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 5.50M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 4, ProductName = "Wine 4", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 5.50M, SubTotalForItem = 0.00M, Genre = "Wine" });
}
更新
在 ProductPage 上,如果用户更改产品的数量,它会在 productPage_ViewModal.WineList、
中自动更新
当用户单击购物车图标时,将在 ProductPage 上调用 OnDisappearing(),将 productPage_ViewModal.WineList 添加到
global ObservableCollection<ProductModel> globalShoppingCartOC
,(存储在App.xaml.cs页面)
从 ShoppingCartPage.xaml.cs 中的 OnAppearing() 开始,ShoppingCartViewModel.ShoppingCartList 通过遍历 globalShoppingCartOC 进行填充,
如果数量大于 0,则添加到 ShoppingCartViewModel.ShoppingCartList,并在 select 前选择器中选择的数量:
Quantity tempQuantity = Model.SelectedQuantity;
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
问题是我可以通过单步执行代码看到 'Model.SelectedQuantity' 将存储正确的值,但它不会在带有选择器的 ShoppingCart 屏幕上更新
<Picker x:Name="scPicker" Title="--Select--" ItemsSource="{Binding ListQuantites, Mode=TwoWay}" SelectedItem="{Binding SelectedQuantity, Mode=TwoWay}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="SCQuantityAndSubtotalUpdated"/>
根据你的代码,我发现 PickerService.GetQuantitiesForProductPage()
PickerService.GetQuantitiesForShoppingcart()
会得到不同的列表,
ProductPage Picker 项目来源:
public static ObservableCollection<Quantity> GetQuantitiesForProductPage()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="0"},
new Quantity() {Key=2, Value="1"},
new Quantity() {Key=3, Value="2"},
new Quantity() {Key=4, Value="3"},
new Quantity() {Key=5, Value="4"},
new Quantity() {Key=6, Value="5"},
new Quantity() {Key=7, Value="6"},
new Quantity() {Key=8, Value="7"},
new Quantity() {Key=9, Value="8"},
new Quantity() {Key=10, Value="9"},
new Quantity() {Key=11, Value="10"}
};
return quantities;
}
ShoppingCartPage Picker 项目来源:
public static ObservableCollection<Quantity> GetQuantitiesForShoppingcart()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="1"},
new Quantity() {Key=2, Value="2"},
new Quantity() {Key=3, Value="3"},
new Quantity() {Key=4, Value="4"},
new Quantity() {Key=5, Value="5"},
new Quantity() {Key=6, Value="6"},
new Quantity() {Key=7, Value="7"},
new Quantity() {Key=8, Value="8"},
new Quantity() {Key=9, Value="9"},
new Quantity() {Key=10, Value="10"},
};
return quantities;
}
所以从 ProductPage 中选择的 SelectedQuantity,在 ShoppingCartPage Picker itemsource 中找不到。 ShoppingCartPage 中的 Picker 不会显示数据。
将 MVVM 与 xamarin 表单结合使用。 ProductPage 包含产品的 ListView。每个产品都有一个选择器。 用户 select 想要购买的商品的数量。用户点击购物车图像。 ShoppingCartPage 加载显示用户已 select 编辑的项目,但选择器为空白。我希望选择器显示从 productaPage 中选择的数量 我已经逐步完成了后面的代码和
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value)
在 ShoppingCartPage 的 OnAppearing() 上存储了正确的数量值,但我不明白为什么选择器没有显示正确的值。
已尝试以下所有建议:
https://forums.xamarin.com/discussion/153788/set-a-picker-selecteditem-on-page-startup
Item to Display for Picker don't show up on load
但仍然无法正常工作有人知道我做错了什么吗?
感谢任何建议
public class ProductModel : INotifyPropertyChanged
{
//Event
public event PropertyChangedEventHandler PropertyChanged;
//Fields
//[PrimaryKey, AutoIncrement]
private int _ProductId;
private string _ProductName;
private string _Quantity;
private string _Description;
private string _Image;
private decimal _Price;
private decimal _SubTotalForItem;
private string _Genre;
public ObservableCollection<Quantity> _ListQuantites;
//Constructor
public ProductModel()
{
//Subscription
this.PropertyChanged += OnPropertyChanged;
}
[PrimaryKey, AutoIncrement]
public int ProductId
{
get { return _ProductId; }
set
{
if (_ProductId == value) return;
_ProductId = value;
OnPropertyChanged();
}
}
//Properties
public string Quantity
{
get
{
return _Quantity;
}
set
{
_Quantity = value;
OnPropertyChanged();
}
}
public ObservableCollection<Quantity> ListQuantites
{
get
{
return _ListQuantites;
}
set
{
_ListQuantites = value;
OnPropertyChanged();
}
}
private Quantity _selectedQuantity;
public Quantity SelectedQuantity
{
get
{
return _selectedQuantity;
}
set
{
if (value == null)
{
_selectedQuantity = _selectedQuantity;
}
else
{
_selectedQuantity = value;
OnPropertyChanged();
}
}
}
[MaxLength(50)]
public string Description
{
get
{
return _Description;
}
set
{
_Description = value;
OnPropertyChanged();
}
}
public string Image
{
get
{
return _Image;
}
set
{
_Image = value;
OnPropertyChanged();
}
}
public decimal Price
{
get
{
return _Price;
}
set
{
_Price = value;
OnPropertyChanged();
}
}
public decimal SubTotalForItem
{
get
{
return _SubTotalForItem;
}
set
{
_SubTotalForItem = value;
OnPropertyChanged();
}
}
public string Genre
{
get
{
return _Genre;
}
set
{
_Genre = value;
OnPropertyChanged();
}
}
public string ProductName
{
get { return _ProductName; }
set
{
_ProductName = value;
OnPropertyChanged();
}
}
//OnPropertyChanged
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SelectedQuantity))
{
//test quantity amount
}
}
// [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
----------------
public class Quantity
{
public int Key { get; set; }
public string Value { get; set; }
}
----------------
public class PickerService
{
public static ObservableCollection<Quantity> GetQuantitiesForProductPage()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="0"},
new Quantity() {Key=2, Value="1"},
new Quantity() {Key=3, Value="2"},
new Quantity() {Key=4, Value="3"},
new Quantity() {Key=5, Value="4"},
new Quantity() {Key=6, Value="5"},
new Quantity() {Key=7, Value="6"},
new Quantity() {Key=8, Value="7"},
new Quantity() {Key=9, Value="8"},
new Quantity() {Key=10, Value="9"},
new Quantity() {Key=11, Value="10"}
};
return quantities;
}
public static ObservableCollection<Quantity> GetQuantitiesForShoppingcart()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="1"},
new Quantity() {Key=2, Value="2"},
new Quantity() {Key=3, Value="3"},
new Quantity() {Key=4, Value="4"},
new Quantity() {Key=5, Value="5"},
new Quantity() {Key=6, Value="6"},
new Quantity() {Key=7, Value="7"},
new Quantity() {Key=8, Value="8"},
new Quantity() {Key=9, Value="9"},
new Quantity() {Key=10, Value="10"},
};
return quantities;
}
}
--------------
public class ShoppingCartViewModel //: INotifyPropertyChanged
{
private ObservableCollection<ProductModel> _shoppingCartList;
public ObservableCollection<ProductModel> ShoppingCartList
{
get
{
return _shoppingCartList;
}
set
{
if (_shoppingCartList == value) return;
_shoppingCartList = value;
}
}
public ShoppingCartViewModel()
{
ShoppingCartList = new ObservableCollection<ProductModel>();
}
}
----------------
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ShoppingCartPage : ContentPage
{
ShoppingCartViewModel ShoppingCartViewModel = new ShoppingCartViewModel();
public decimal TotalForAllItems;
public ObservableCollection<Quantity> List_Quantites { get; set; }
public ShoppingCartPage()
{
InitializeComponent();
BindingContext = ShoppingCartViewModel;
}
public int CalculateQuantityOfItemsInShoppingCart()
{
int quantityOfProducts = 0;
if (ShoppingCartViewModel.ShoppingCartList != null)
{
foreach (var product in ShoppingCartViewModel.ShoppingCartList)
{
if (product.SelectedQuantity != null)
{
quantityOfProducts += Convert.ToInt32(product.SelectedQuantity.Value);
}
}
}
return quantityOfProducts;
}
protected override void OnDisappearing()
{
App.globalShoppingCartOC = ShoppingCartViewModel.ShoppingCartList;
}
protected override void OnAppearing()
{
base.OnAppearing();
TotalForAllItems = 0.00M;
List_Quantites = PickerService.GetQuantitiesForShoppingcart();
ShoppingCartViewModel.ShoppingCartList.Clear();
if (App.globalShoppingCartOC != null)
{
foreach (ProductModel Model in App.globalShoppingCartOC)
{
if (Model.SelectedQuantity != null)
{
var _quantity = Convert.ToDecimal(Model.SelectedQuantity.Value);
if (_quantity > 0)
{
Model.SubTotalForItem = _quantity * Model.Price;
//this line resets Model.SelectedQuantity to 0, so need to re-populate with tempQuantity value
Quantity tempQuantity = Model.SelectedQuantity;
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
ShoppingCartViewModel.ShoppingCartList.Add(Model);
TotalForAllItems += Model.SubTotalForItem;
}
}
}
SubTotalForAllItems.Text = TotalForAllItems.ToString();
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
protected async void SI_Invoked(object sender, EventArgs e)
{
var si = sender as SwipeItem;
var productToRemove = si.CommandParameter as ProductModel;
var action = await DisplayAlert("Are you sure you want to remove ", productToRemove.ProductName + ".", "Yes", "No");
if (action)
{
ShoppingCartViewModel.ShoppingCartList.Remove(productToRemove);
Quantity tempQuantity = productToRemove.SelectedQuantity;
decimal tempQuantityValue = Convert.ToDecimal(tempQuantity.Value);
decimal subtotalToRemove = productToRemove.Price * tempQuantityValue;
TotalForAllItems -= subtotalToRemove;
SubTotalForAllItems.Text = TotalForAllItems.ToString();
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
}
public void SCQuantityAndSubtotalUpdated(object sender, EventArgs e)
{
TotalForAllItems = 0.00M;
if (ShoppingCartViewModel.ShoppingCartList != null)
{
foreach (ProductModel Model in ShoppingCartViewModel.ShoppingCartList)
{
var _quantity = Convert.ToDecimal(Model.SelectedQuantity.Value);
if (_quantity > 0)
{
Model.SubTotalForItem = _quantity * Model.Price;
TotalForAllItems += Model.SubTotalForItem;
}
}
SubTotalForAllItems.Text = TotalForAllItems.ToString();
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
private void PlaceOrder_BtnClicked(object sender, EventArgs e)
{
}
}
-------------------------
<ContentPage.ToolbarItems>
<ToolbarItem Name="shoppingCartImg" Icon="shopping_cart.png" Priority="0" Order="Primary"/>
<ToolbarItem x:Name="NoItemsInShoppingCart" Priority="0" Order="Primary"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView ItemsSource="{Binding ShoppingCartList}" IsVisible="True" VerticalOptions="FillAndExpand" HasUnevenRows="True">
<ListView.Header>
<Button Text="Place Order" Clicked="PlaceOrder_BtnClicked"/>
</ListView.Header>
<ListView.Footer>
<Label x:Name="SubTotalForAllItems" HorizontalTextAlignment="End" VerticalTextAlignment="Start" Margin="20,20" FontAttributes="Bold"/>
</ListView.Footer>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems Mode="Reveal">
<SwipeItem Text="Details" IconImageSource="xamarin_logo.png" CommandParameter="{Binding .}" BackgroundColor="LightBlue" Invoked="SI_Invoked">
</SwipeItem>
</SwipeItems>
</SwipeView.LeftItems>
<!--Content of Swipe View -->
<StackLayout BackgroundColor="Green" HorizontalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding ProductId}" VerticalOptions="End" IsVisible="False"/>
<controls:CircleImage Grid.Column="1" Grid.Row="0" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
<Label Grid.Column="2" Grid.Row="0" Text="{Binding ProductName}" VerticalOptions="Start"/>
<Label Grid.Column="2" Grid.Row="1" Text="{Binding Description}" VerticalOptions="End"/>
<Label Grid.Column="3" Grid.Row="0" VerticalOptions="Start" Text="{Binding SubTotalForItem, StringFormat='£{0:0.00}'}"/>
<Picker x:Name="scPicker" ItemsSource="{Binding ListQuantites, Mode=TwoWay}" SelectedItem="{Binding SelectedQuantity, Mode=TwoWay}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="SCQuantityAndSubtotalUpdated"/>
</Grid>
</StackLayout>
</SwipeView>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
-------------------------
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductPage : ContentPage
{
public ProductPageViewModel productPage_ViewModal;
MainPage RootPage { get => Application.Current.MainPage as MainPage; }
public ProductPage()
{
InitializeComponent();
productPage_ViewModal = new ProductPageViewModel();
BindingContext = productPage_ViewModal;
}
protected override void OnDisappearing()
{
App.globalShoppingCartOC = productPage_ViewModal.WineList;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (App.globalShoppingCartOC != null)
{
//First need to check shoppingCart list for product, if it has been removed in SC,
//then set quantity to 0
foreach (var product in productPage_ViewModal.WineList)
{
var doesProductExistInShoppingCart = App.globalShoppingCartOC.Where(x => x.ProductId == product.ProductId).FirstOrDefault();
if(doesProductExistInShoppingCart == null)
{
if (productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity != null)
{
Quantity tempQuantity = new Quantity() { Key = 1, Value = "0" };
product.SelectedQuantity = productPage_ViewModal.List_Quantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
product.ListQuantites = PickerService.GetQuantitiesForProductPage();
// productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity.Value = "0";
}
}
}
//Can then update correct quantity for other products still in SC list
foreach (var product in App.globalShoppingCartOC)
{
if (productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity != null)
{
Quantity tempQuantity = product.SelectedQuantity;
product.SelectedQuantity = productPage_ViewModal.List_Quantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
product.ListQuantites = PickerService.GetQuantitiesForProductPage();
//productPage_ViewModal.WineList.Where(x => x.ProductId == product.ProductId).FirstOrDefault().SelectedQuantity.Value = product.SelectedQuantity.Value;
}
}
}
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
private async void ShoppingCartClicked(object sender, EventArgs e)
{
MenuPage tempMenu = new MenuPage();
int IdOfMenuClicked = tempMenu.GetIdForNavigationMenu("Shopping Cart");
await RootPage.NavigateFromMenu(IdOfMenuClicked);
}
public void QuantityChanged(object sender, EventArgs e)
{
NoItemsInShoppingCart.Text = CalculateQuantityOfItemsInShoppingCart().ToString();
}
public int CalculateQuantityOfItemsInShoppingCart()
{
int quantityOfProducts = 0;
if (productPage_ViewModal.WineList != null)
{
foreach (var product in productPage_ViewModal.WineList)
{
if (product.SelectedQuantity != null)
{
quantityOfProducts += Convert.ToInt32(product.SelectedQuantity.Value);
}
}
}
return quantityOfProducts;
}
}
-------------------------
Title="ProductPage">
<ContentPage.ToolbarItems>
<ToolbarItem Name="shoppingCartImg" Icon="shopping_cart.png" Priority="0" Order="Primary" Activated="ShoppingCartClicked"/>
<ToolbarItem x:Name="NoItemsInShoppingCart" Priority="0" Order="Primary" Activated="ShoppingCartClicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView IsVisible="True" VerticalOptions="FillAndExpand" HasUnevenRows="True" ItemsSource="{Binding WineList}"> <!--HeightRequest="1500"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="Green" HorizontalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding ProductId}" VerticalOptions="End" IsVisible="False"/>
<controls:CircleImage Grid.Column="1" Grid.Row="0" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
<Label Grid.Column="2" Grid.Row="0" Text="{Binding ProductName}" VerticalOptions="Start"/>
<Label Grid.Column="2" Grid.Row="1" Text="{Binding Description}" VerticalOptions="End"/>
<Label Grid.Column="3" Grid.Row="0" VerticalOptions="Start" Text="{Binding Price, StringFormat='£{0:0.00}'}"/>
<Picker x:Name="productPicker" ItemsSource="{Binding ListQuantites}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="QuantityChanged" SelectedItem ="{Binding SelectedQuantity}"/>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
----------------------------------------------
public class ProductPageViewModel : BindableObject, INotifyPropertyChanged
{
public ObservableCollection<ProductModel> WineList { get; set; }
public ObservableCollection<Quantity> List_Quantites { get; set; }
public ProductPageViewModel()
{
List_Quantites = PickerService.GetQuantitiesForProductPage();//.OrderBy(c => c.Value).ToList();
WineList = new ObservableCollection<ProductModel>();
WineList.Add(new ProductModel { ProductId = 1, ProductName = "Wine 1", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 10.00M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 2, ProductName = "Wine 2", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 10.00M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 3, ProductName = "Wine 3", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 5.50M, SubTotalForItem = 0.00M, Genre = "Wine" });
WineList.Add(new ProductModel { ProductId = 4, ProductName = "Wine 4", ListQuantites = List_Quantites, Image = "wine.jpg", Quantity = "0", Description = "700ml", Price = 5.50M, SubTotalForItem = 0.00M, Genre = "Wine" });
}
更新
在 ProductPage 上,如果用户更改产品的数量,它会在 productPage_ViewModal.WineList、
中自动更新当用户单击购物车图标时,将在 ProductPage 上调用 OnDisappearing(),将 productPage_ViewModal.WineList 添加到
global ObservableCollection<ProductModel> globalShoppingCartOC
,(存储在App.xaml.cs页面)
从 ShoppingCartPage.xaml.cs 中的 OnAppearing() 开始,ShoppingCartViewModel.ShoppingCartList 通过遍历 globalShoppingCartOC 进行填充,
如果数量大于 0,则添加到 ShoppingCartViewModel.ShoppingCartList,并在 select 前选择器中选择的数量:
Quantity tempQuantity = Model.SelectedQuantity;
Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value);
问题是我可以通过单步执行代码看到 'Model.SelectedQuantity' 将存储正确的值,但它不会在带有选择器的 ShoppingCart 屏幕上更新
<Picker x:Name="scPicker" Title="--Select--" ItemsSource="{Binding ListQuantites, Mode=TwoWay}" SelectedItem="{Binding SelectedQuantity, Mode=TwoWay}" ItemDisplayBinding="{Binding Value}" SelectedIndexChanged="SCQuantityAndSubtotalUpdated"/>
根据你的代码,我发现 PickerService.GetQuantitiesForProductPage()
PickerService.GetQuantitiesForShoppingcart()
会得到不同的列表,
ProductPage Picker 项目来源:
public static ObservableCollection<Quantity> GetQuantitiesForProductPage()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="0"},
new Quantity() {Key=2, Value="1"},
new Quantity() {Key=3, Value="2"},
new Quantity() {Key=4, Value="3"},
new Quantity() {Key=5, Value="4"},
new Quantity() {Key=6, Value="5"},
new Quantity() {Key=7, Value="6"},
new Quantity() {Key=8, Value="7"},
new Quantity() {Key=9, Value="8"},
new Quantity() {Key=10, Value="9"},
new Quantity() {Key=11, Value="10"}
};
return quantities;
}
ShoppingCartPage Picker 项目来源:
public static ObservableCollection<Quantity> GetQuantitiesForShoppingcart()
{
var quantities = new ObservableCollection<Quantity>()
{
new Quantity() {Key=1, Value="1"},
new Quantity() {Key=2, Value="2"},
new Quantity() {Key=3, Value="3"},
new Quantity() {Key=4, Value="4"},
new Quantity() {Key=5, Value="5"},
new Quantity() {Key=6, Value="6"},
new Quantity() {Key=7, Value="7"},
new Quantity() {Key=8, Value="8"},
new Quantity() {Key=9, Value="9"},
new Quantity() {Key=10, Value="10"},
};
return quantities;
}
所以从 ProductPage 中选择的 SelectedQuantity,在 ShoppingCartPage Picker itemsource 中找不到。 ShoppingCartPage 中的 Picker 不会显示数据。