C# xamarin表单-与选择器的双向绑定-为什么我不能从代码隐藏更新选择器?
“我的产品”页面仅显示“产品名称”和“数量”,数量显示/绑定到选择器 出于测试目的,只有2个产品从VM加载。葡萄酒1和葡萄酒2 当应用程序加载时,为什么选择器为空且未选择任何值。当每个项目的数量设置为1时,从VM加载时 数量设置为1,拾取程序在最初加载时不更新,我知道这一点,因为如果我单击空的拾取程序并选择1。因为代码命中,所以什么也没有发生C# xamarin表单-与选择器的双向绑定-为什么我不能从代码隐藏更新选择器?,c#,xaml,xamarin,xamarin.forms,picker,C#,Xaml,Xamarin,Xamarin.forms,Picker,“我的产品”页面仅显示“产品名称”和“数量”,数量显示/绑定到选择器 出于测试目的,只有2个产品从VM加载。葡萄酒1和葡萄酒2 当应用程序加载时,为什么选择器为空且未选择任何值。当每个项目的数量设置为1时,从VM加载时 数量设置为1,拾取程序在最初加载时不更新,我知道这一点,因为如果我单击空的拾取程序并选择1。因为代码命中,所以什么也没有发生 if (quantity != value) //如果选择的数量1在代码隐藏中已为1,则不会调用propertyChanged from setter
if (quantity != value)
//如果选择的数量1在代码隐藏中已为1,则不会调用propertyChanged from setter in quantity
还有。。。
如果我选择选择器并选择另一个数字,例如4。数量设置器被命中,OnPropertyChanged被命中,4显示在选择器上。
(我甚至测试了在选择3时更改产品名称)
这起作用了
我知道这一切都是可行的,因为我已经通过了代码然而,现在发生的另一个问题是,由于某种原因,每次单击代码后,代码都会再次命中数量get/set并将该值设置为0。
因此,例如,如果单击4,选择器将在屏幕上更新为4,然后如果我通过单步执行代码,将再次调用数量设置器,将值设置为0,从而在选择器中不选择任何内容。将其保留为空,就像最初加载时一样
任何有助于解决此问题的帮助都将不胜感激,谢谢
谢谢你的帮助
public class ProductModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int quantity;
private string productName;
public ProductModel()
{ }
[PrimaryKey, AutoIncrement]
public int ProductId { get; set; }
[MaxLength(50)]
public string ProductName
{
get
{
return productName;
}
set
{
productName = value;
OnPropertyChanged();
}
}
public int Quantity
{
get
{
return quantity;
}
set
{
if (quantity != value)
{
quantity = value;
OnPropertyChanged();
//test to check if binding works, successfully changed ProductName to "test" if 3 is picked from picker
if (quantity == 3)
ProductName = "test;";
}
}
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class ProductPageViewModel : BindableObject
{
public ObservableCollection<ProductModel> WineList { get; set; }
public ProductPageViewModel ()
{
WineList = new ObservableCollection<ProductModel>();
WineList.Add(new ProductModel { ProductId = 1, ProductName = "Wine 1", Quantity = 1});
WineList.Add(new ProductModel { ProductId = 2, ProductName = "Wine 2", Quantity = 1});
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScrollApp2.Views.ProductPage">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="producttablelist" IsVisible="True" VerticalOptions="FillAndExpand" HasUnevenRows="True" ItemsSource="{Binding WineList}" HeightRequest="1500">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HeightRequest="120" BackgroundColor="Green" HorizontalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding ProductName}" TextColor="Black" VerticalOptions="Start"></Label>
<Picker Grid.Column="1" Grid.Row="0" SelectedItem="{Binding Quantity,Mode=TwoWay}">
<Picker.Items>
<x:String>0</x:String>
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
<x:String>6</x:String>
</Picker.Items>
</Picker>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
namespace ScrollApp2.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductPage : ContentPage
{
public ProductPage()
{
InitializeComponent();
BindingContext = new ProductPageViewModel();
}
}
}
公共类ProductModel:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私人整数数量;
私有字符串产品名称;
公共产品模型()
{ }
[主密钥,自动增量]
public int ProductId{get;set;}
[MaxLength(50)]
公共字符串产品名称
{
得到
{
返回产品名称;
}
设置
{
产品名称=价值;
OnPropertyChanged();
}
}
公共整数
{
得到
{
退货数量;
}
设置
{
如果(数量!=值)
{
数量=价值;
OnPropertyChanged();
//测试若要检查绑定是否有效,请成功将ProductName更改为“test”(如果从选择器中选取了3)
如果(数量=3)
ProductName=“测试;”;
}
}
}
受保护的void OnPropertyChanged([CallerMemberName]字符串名称=null)
{
var changed=Property changed;
如果(已更改==null)
返回;
Invoke(这个,新属性changedeventargs(名称));
}
}
公共类ProductPageViewModel:BindableObject
{
公共ObservableCollection酒单{get;set;}
公共产品页面视图模型()
{
WineList=新的ObservableCollection();
添加(新产品模型{ProductId=1,ProductName=“Wine 1”,数量=1});
添加(新产品模型{ProductId=2,ProductName=“Wine 2”,数量=1});
}
0
1.
2.
3.
4.
5.
6.
名称空间ScrollApp2.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
公共部分类ProductPage:ContentPage
{
公共产品页()
{
初始化组件();
BindingContext=new ProductPageViewModel();
}
}
}
您的ProductModel
类不是从INotifyPropertyChanged
接口继承的,您需要将接口添加到类中并实现它,同时确保在Quantity
setter中引发INotifyPropertyChanged.PropertyChanged
事件
此时您可能需要创建一个ProductViewModel
,因为我不确定您是否要将INotifyPropertyChanged
添加到类似ProductModel
的POCO类中
请不要用其他问题编辑您的问题,打开一个新问题。您以前的问题可能有助于其他人在更改不是从
IPropertyChanged
继承的类的属性时遇到同样的UI未更新问题。我以前的回答现在与新问题无关,并且永远不会被更新不适合任何其他人
对于您的新问题,您的Quantity
类型为int
,您的选取器类型为i
public class ProductModel : INotifyPropertyChanged {
//Event
public event PropertyChangedEventHandler PropertyChanged;
//Fields
private string _ProductName;
private int _Quantity;
//Properties
public int Quantity {
get { return _Quantity; }
set {
_Quantity = value;
OnPropertyChanged();
}
}
public string ProductName {
get { return _ProductName; }
set {
_ProductName = value;
OnPropertyChanged();
}
}
//Constructor
public ProductModel() {
//Subscription
this.PropertyChanged += OnPropertyChanged;
}
//OnPropertyChanged
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(Quantity)) {
//Do anything that needs doing when the Quantity changes here...
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}