Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# xamarin表单-与选择器的双向绑定-为什么我不能从代码隐藏更新选择器?_C#_Xaml_Xamarin_Xamarin.forms_Picker - Fatal编程技术网

C# xamarin表单-与选择器的双向绑定-为什么我不能从代码隐藏更新选择器?

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

“我的产品”页面仅显示“产品名称”和“数量”,数量显示/绑定到选择器

出于测试目的,只有2个产品从VM加载。葡萄酒1和葡萄酒2

当应用程序加载时,为什么选择器为空且未选择任何值。当每个项目的数量设置为1时,从VM加载时

数量设置为1,拾取程序在最初加载时不更新,我知道这一点,因为如果我单击空的拾取程序并选择1。因为代码命中,所以什么也没有发生

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