尝试在列表视图 MVVM Xamarin 中设置选择器 [英] Trying to set picker within listview MVVM Xamarin

查看:22
本文介绍了尝试在列表视图 MVVM Xamarin 中设置选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试通过使用 SelectedItem 将初始值设置为选择器.如果选择器不在列表视图中,我可以毫无问题地执行此操作.但是,一旦我尝试在列表视图中完成此操作,就没有骰子.

我永远无法让选择器显示最初下载的值.如果我对条目使用相同的绑定,它会显示预期的字符串.

想法??


这可以在这个简单的独立项目中重现.请帮忙.谢谢.

clRecipeIngredients

公共类 clRecipeIngredient{公共 int RecipeIngredientsID { 获取;放;}公共 int RecipeIDLookedUP { 获取;放;}公共 int IngredientIDLookedUp { 获取;放;}公共双数量{得到;放;}公共 int UnitIDLookedUp { 获取;放;}public bool HiddenFlag { 获取;放;}公共字符串 UnitName { get;放;}公共字符串成分名称 { 获取;放;}公共字符串注释 { 获取;放;}

解决方案

我检查了你的示例,你可以像下面这样修改它.

在 Xaml 中

在视图模型中

ObservableCollection 在默认情况下实现了接口 INotifyPropertyChanged.因此,您可以简化 ViewModel 中的代码.

注意:您不能将 SelectItem 的值直接设置为字符串,即使它们相等.你需要像下面这样设置

 ing.IngredientName = listIngredients[0];

所以 ViewModel 可能会喜欢

公共类 testPageViewModel : BaseViewModel{公共 ObservableCollection下载的食谱成分{得到;设置;}公共 ObservableCollection;列表成分{获取;放;}//私有clRecipeDataBase recipeDataBase;公共 testPageViewModel(){//recipeDataBase = new clRecipeDataBase();btnPress = new Command(madeIt);DownloadRecipeIngredients = new ObservableCollection();listIngredients = new ObservableCollection();获取数据();}异步 void getData(){//选择器成分数据//clIngredient[] arrayIngredients = await recipeDataBase.getIngredientData();//clIngredient[] arrayIngredients = new clIngredient[5];//arrayIngredients[0].IngredientName = "Apple";//arrayIngredients[1].IngredientName = "Salt";//arrayIngredients[2].IngredientName = "Buter";//arrayIngredients[3].IngredientName = "面粉";//arrayIngredients[4].IngredientName = "Egg";listIngredients.Add(苹果");listIngredients.Add(盐");listIngredients.Add(黄油");listIngredients.Add(面粉");listIngredients.Add(鸡蛋");//for (int i = 0; i < arrayIngredients.Length; i++)//{//_listIngredients.Add(arrayIngredients[i].IngredientName);//}//clRecipeIngredient[] arryRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310);//硬编码到脆皮比萨食谱clRecipeIngredient ing = new clRecipeIngredient();ing.IngredientName = listIngredients[0];ing.Quantity = 1;ing.UnitName = "杯子";ing.Comments = "Comments0";clRecipeIngredient ing2 = new clRecipeIngredient();ing2.IngredientName = listIngredients[1];ing2.Quantity = 2;ing2.UnitName =整体";ing2.Comments = "Comments1";下载了RecipeIngredients.Add(ing);下载的食谱成分.添加(ing2);}公共 ICommand btnPress { 获取;私人订制;}void madeIt(clRecipeIngredient x){Console.WriteLine(x.IngredientName + " -- " + x.Comments);//_downloadedRecipeIngredients.Remove(x);}}

并且不要忘记在您的模型中实现 INotifyPropertyChanged,因为 IngredientName 的值将被更改.

公共类 clRecipeIngredient : INotifyPropertyChanged{公共事件 PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));}//...字符串成分名称;公共字符串成分名称{得到{返回成分名称;}放{如果(成分名称!= 值){成分名称 = 值;OnPropertyChanged(成分名称");}}}//...}

Trying to set the initial value to a picker through the use of SelectedItem. I can do this without any issue if the picker isn't within a listview. However, once I try to accomplish this in a listview no dice.

I never can get the picker to display the initially downloaded value. If I use the same binding for an entry it displays the expected string.

Thoughts??


This can be reproduced in this simplistic standalone project. Please help. Thanks.

https://github.com/smarcus3/DebuggingProject


XAML

<ListView x:Name="listView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding downloadedRecipeIngredients}">  <!--SelectedItem="{Binding SelectedItem}"-->
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <!-- Element Label -->
                            <Entry VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" Text="{Binding IngredientName}"/>
                            <!--<Picker x:Name="pickerIngredient" HorizontalOptions = "StartAndExpand" ItemsSource="{Binding listIngredients}" BindingContext="{Binding Source={x:Reference Page}, Path=BindingContext}" SelectedItem="{Binding IngredientName}" WidthRequest="100"/>-->
                            <Picker x:Name="pickerIngredientancestor" HorizontalOptions = "StartAndExpand" WidthRequest="100" ItemsSource="{Binding listIngredients, Source={RelativeSource AncestorType={x:Type viewModel:testPageViewModel}}}" SelectedItem="{Binding IngredientName}"/>
                            <Entry Text="{Binding Quantity}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
                            <Entry Text="{Binding UnitName}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
                            <Entry Text="{Binding Comments}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
                            <!-- Assessment Menu Icon -->
                            <Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand">
                                <Label.GestureRecognizers>
                                    <TapGestureRecognizer Command="{Binding Path=BindingContext.btnPress, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
                                </Label.GestureRecognizers>
                            </Label>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

VIEW MODEL

public class testPageViewModel : BaseViewModel
{
   
    clRecipeIngredient[] _downloadedRecipeIngredients;
    public clRecipeIngredient[] downloadedRecipeIngredients
    { 
        get { 
            return _downloadedRecipeIngredients; 
        } 
        set 
        {
            //if (downloadedRecipeIngredients != value)
            //{
                _downloadedRecipeIngredients = value;
                OnPropertyChanged("downloadedRecipeIngredients");
            //}
        } 
    }

    //Lists for Pickers
    ObservableCollection<string> _listIngredients = new ObservableCollection<string>();
    public ObservableCollection<string> listIngredients { get { return _listIngredients; } }


    private clRecipeDataBase recipeDataBase;

    public testPageViewModel()
    {
        recipeDataBase = new clRecipeDataBase();

        btnPress = new Command<clRecipeIngredient>(madeIt);

        getData();
    }

    async void getData()
    {
        //PICKER INGREDIENT DATA
        clIngredient[] tmp = await recipeDataBase.getIngredientData();
        for (int i = 0; i < tmp.Length; i++)
        {
            _listIngredients.Add(tmp[i].IngredientName);
        }

        _downloadedRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310); //HARDCODED TO CRISPY PIZZA RECIPE

       
        OnPropertyChanged("downloadedRecipeIngredients");

    }

    public ICommand btnPress { get; private set; }
    void madeIt(clRecipeIngredient x)
    {
        Console.WriteLine(x.IngredientName + " -- " + x.Comments);

        //_downloadedRecipeIngredients.Remove(x);

    }



}


clRecipeIngredients

public class clRecipeIngredient
{
    public int RecipeIngredientsID { get; set; }
    public int RecipeIDLookedUP { get; set; }
    public int IngredientIDLookedUp { get; set; }
    public double Quantity { get; set; }
    public int UnitIDLookedUp { get; set; }
    public bool HiddenFlag { get; set; }
    public string UnitName { get; set; }
    public string IngredientName { get; set; }
    public string Comments { get; set; }

解决方案

I checked your sample and you could modify it like following .

in Xaml

<Picker HorizontalOptions = "StartAndExpand" WidthRequest="100" ItemsSource="{Binding Path=BindingContext.listIngredients, Source={x:Reference Page}}" SelectedItem="{Binding IngredientName, Mode=TwoWay}" />

in ViewModel

ObservableCollection had implemented the interface INotifyPropertyChanged in default . So you could simplify the code in your ViewModel .

Note : You could not set the value of SelectItem as a string directly even if they are equal . You need to set it like following

 ing.IngredientName = listIngredients[0];

So the ViewModel could like

public class testPageViewModel : BaseViewModel
{

   
    public ObservableCollection<clRecipeIngredient> downloadedRecipeIngredients
    {
        get;set;
    }

 
  
    public ObservableCollection<string> listIngredients { get; set; }

   

    //private clRecipeDataBase recipeDataBase;

    public testPageViewModel()
    {
        //recipeDataBase = new clRecipeDataBase();

        btnPress = new Command<clRecipeIngredient>(madeIt);

        downloadedRecipeIngredients = new ObservableCollection<clRecipeIngredient>();
        listIngredients = new ObservableCollection<string>();
        getData();
    }

    async void getData()
    {
        //PICKER INGREDIENT DATA
        //clIngredient[] arrayIngredients = await recipeDataBase.getIngredientData();

        //clIngredient[] arrayIngredients = new clIngredient[5];

        //arrayIngredients[0].IngredientName = "Apple";
        //arrayIngredients[1].IngredientName = "Salt";
        //arrayIngredients[2].IngredientName = "Buuter";
        //arrayIngredients[3].IngredientName = "Flour";
        //arrayIngredients[4].IngredientName = "Egg";

        listIngredients.Add("Apple");
        listIngredients.Add("Salt");
        listIngredients.Add("Butter");
        listIngredients.Add("Flour");
        listIngredients.Add("Egg");

        //for (int i = 0; i < arrayIngredients.Length; i++)
        //{
        //    _listIngredients.Add(arrayIngredients[i].IngredientName);
        //}

        //clRecipeIngredient[] arryRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310); //HARDCODED TO CRISPY PIZZA RECIPE

        clRecipeIngredient ing = new clRecipeIngredient();
      
        ing.IngredientName = listIngredients[0];
        ing.Quantity = 1;
        ing.UnitName = "Cups";
        ing.Comments = "Comments0";
       
        clRecipeIngredient ing2 = new clRecipeIngredient();

        ing2.IngredientName = listIngredients[1];
        ing2.Quantity = 2;
        ing2.UnitName = "Whole";
        ing2.Comments = "Comments1";

        downloadedRecipeIngredients.Add(ing);
        downloadedRecipeIngredients.Add(ing2);


       


    }

    public ICommand btnPress { get; private set; }
    void madeIt(clRecipeIngredient x)
    {
        Console.WriteLine(x.IngredientName + " -- " + x.Comments);

        //_downloadedRecipeIngredients.Remove(x);

    }



}

And don't forget to implement INotifyPropertyChanged in your model as the value of IngredientName will been changed .

public class clRecipeIngredient : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(
    [CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
    }

   //...
    string ingredientName;

    public string IngredientName
    {
        get
        {
            return ingredientName;
        }
        set
        {
            if (ingredientName != value)
            {
                ingredientName = value;
                OnPropertyChanged("IngredientName");
            }
        }
    }

   //...
}

这篇关于尝试在列表视图 MVVM Xamarin 中设置选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆