xamarin表单选择器在页面加载时不显示任何值



使用带有xamarin形式的MVVM。ProductPage包含产品的ListView。每个产品都有一个选择器。用户为他们想要购买的商品选择数量。用户单击购物车图像。ShoppingCartPage加载显示用户已选择但选择器为空的项目。我希望选择器显示从产品中选择的数量页面我已经浏览了后面的代码和

Model.ListQuantites = List_Quantites;
Model.SelectedQuantity = Model.ListQuantites.SingleOrDefault(p => p.Key == tempQuantity.Key && p.Value == tempQuantity.Value)

正在ShoppingCartPage中的OnAppearing((上存储正确的数量值,但我不明白picker为什么没有显示正确的值。

尝试了以下所有建议:

如何在页面加载时显示选择器而不点击标题Xamarin.Forms

https://forums.xamarin.com/discussion/153788/set-a-picker-selecteditem-on-page-startup

xamarin.forms使用选择器更新Listview

要为选取器显示的项目don';t出现在装载上

但仍然无法工作有人知道我做错了什么吗?

谢谢你的任何建议

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" });
}

更新

在产品页面上,如果用户更改产品的数量,则会在产品页面_ViewModal.WineList、中自动更新

当用户单击shoppingCart图标时,会在ProductPage上调用OnDisappearing((,将ProductPage_ViewModal.WineList添加到global ObservableCollection<ProductModel> globalShoppingCartOC,(存储在App.xaml.cs页面中(

从ShoppingCartPage.xaml.cs中的OnAppearing((,Shopping卡特ViewModel.ShoppingCartList是通过迭代全局Shopping卡特尔OC、来填充的

如果数量大于0,请添加到ShoppingCartViewModel.ShoppingCartList中,并使用预先选择在拣选器中选择的数量

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选取器项目来源:

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;
}

因此,在ShoppingCartPage选取器项源中找不到从ProductPage中选择的SelectedQuantity。ShoppingCartPage中的选取器将不显示数据。

最新更新