xamarin 表单 - 与选择器的两种方式绑定 - 为啥我不能从后面的代码更新选择器?
Posted
技术标签:
【中文标题】xamarin 表单 - 与选择器的两种方式绑定 - 为啥我不能从后面的代码更新选择器?【英文标题】:xamarin forms - two way binding with a picker - why cant I update a picker from code behind?xamarin 表单 - 与选择器的两种方式绑定 - 为什么我不能从后面的代码更新选择器? 【发布时间】:2020-10-17 20:53:43 【问题描述】:我的产品页面仅显示“产品名称”和“数量”,数量显示/绑定到选择器。
出于测试目的,仅从 VM 加载了 2 个产品。葡萄酒 1 和葡萄酒 2。
应用程序加载时,为什么选择器是空的,没有选择任何值。当每个项目的数量设置为 1 时,从 VM 加载时
数量设置为 1,选择器在最初加载时没有更新,我知道这是因为如果我单击空选择器并选择 1。没有任何反应,因为代码命中
if (quantity != value)
//其中选择的数量1在后面的代码中已经是1,所以不会在数量中从setter调用propertyChanged,
还有... 如果我选择选择器并选择另一个数字,例如 4。数量上的setter被击中,OnPropertyChanged被击中,picker上显示4。 (如果选择了 3,我什至测试了更改产品名称) 这行得通。
我知道这一切都有效,因为我已经逐步完成了代码。 但是现在发生的另一个问题是,由于某种原因,代码在每次单击后再次达到 get/set AGAIN 的数量并将值设置为 0。
因此,例如如果单击 4,则选择器将在屏幕上更新为 4,然后如果我通过单步执行代码,再次调用数量设置器,将值设置为 0,因此什么都不选择在选择器中。将其留空,就像它最初加载时一样。
任何有助于解决此问题的帮助将不胜感激,感谢 Y
感谢 Y 提供的任何帮助
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();
【问题讨论】:
您不需要在数量选择器上使用“SelectedIndexChanged="QuantityChanged"”,因为您已绑定到属性,您可以在属性更改时简单地处理该代码。您需要将以下代码添加到空白的“ProductModel”构造函数中。 “this.PropertyChanged += OnPropertyChanged”,并重写捕获事件的方法。然后在属性发生变化时处理所需的代码 == nameof(Quantity) 感谢您的回答,我已尽力按照您的建议进行操作,但遇到了困难,请查看更新后的 Q 任何帮助将不胜感激,谢谢 Y 是的,你现在很接近了。我将转到一个实际的帖子,以便更轻松地格式化代码。 【参考方案1】:您的ProductModel
类不继承自INotifyPropertyChanged
接口,您需要将接口添加到您的类并实现它,同时确保在Quantity
setter 中引发INotifyPropertyChanged.PropertyChanged
事件.
此时您可能想要创建一个ProductViewModel
,因为我不确定您是否要将INotifyPropertyChanged
添加到像ProductModel
这样的POCO 类中。
请不要用其他问题编辑您的问题,请打开一个新问题。您之前的问题可能已经帮助其他人在更改不从IPropertyChanged
继承的类的属性时面临相同的 UI 未更新问题。我之前的答案现在与新问题无关,并且永远不会使其他任何人受益。
对于您的新问题,您的Quantity
类型为int
,您的选择器项目类型为string
,将Quantity
类型更改为string
应该有助于解决您的问题,您也可以使用@987654335 @ 而不是 SelectedItem
如果项目的索引匹配。
<Picker SelectedIndex="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>
【讨论】:
感谢您的回答,我已尽力按照您的建议进行操作,但遇到了困难,请查看更新后的 Q 任何帮助将不胜感激,谢谢 Y 感谢您抽出宝贵时间提供帮助,它解决了“当应用程序加载时,为什么选择器为空且未选择任何值的问题。当每个项目的数量设置为 1 时,从 VM 加载时。我将此标记为正确答案,但我需要两个答案来解决我的问题,所以写了另一个 Q 并评论说 Q 的第二部分也由 ReRoute 回答,同样是 Roger,感谢您帮助我解决这个问题。非常感激。对于未来的裁判将知道将 1 个问题保留在 1 个帖子中,并对任何混淆表示歉意 ***.com/questions/64437205/…【参考方案2】:看起来您已经在您的ProductModel
上正确实现了INotifyPropertyChanged
,但现在您需要在ProductModel
类的构造函数中订阅它。
我已经对您正在寻找的内容进行了简单的实现(我排除了您的其余代码,以便更容易消化)
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));
如果这能让你继续前进,请告诉我
【讨论】:
非常感谢您提供的帮助。我犯了需要两个问题来解决我的问题的错误。我已经标记了另一个答案,因为它有助于解决问题的第一部分,但我需要您的答案来帮助正确回发和更新。请接受我的道歉或困惑。我想感谢您的帮助,所以我写了另一个 Q,如果您在那里发布您的答案,我会将其标记为正确。再次感谢您花时间帮助***.com/questions/64437205/… 没关系。我很高兴你让它工作了。不用担心到期的信用,我在这里帮助人们享受乐趣,因为我喜欢编码。以上是关于xamarin 表单 - 与选择器的两种方式绑定 - 为啥我不能从后面的代码更新选择器?的主要内容,如果未能解决你的问题,请参考以下文章
[微信小程序] 微信小程序下拉滚动选择器picker绑定数据的两种方式