【问题标题】:Trying to set picker within listview MVVM Xamarin尝试在 listview MVVM Xamarin 中设置选择器
【发布时间】:2020-07-06 16:13:29
【问题描述】:

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

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

想法??


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

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>

查看模型

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

【问题讨论】:

  • 我在你的虚拟机中看不到 IngredientName 属性
  • IngredientName 是下载的RecipeIngredients 的属性。此外,如果 _downloadedRecipeIngredients 设置为 ObservableCollection 而不是数组,当将项目添加到数组时,IngredientName 将替换为 NULL。
  • downloadedRecipeIngredients 是一个数组,它不能有属性。你的意思是clRecipeIngredient
  • clRecipeIngredient 是一个自定义类。 DownloadedRecipeIngredients 是一个数组。数组的每个元素都显示在列表视图上,但我无法在选择器成分名称上显示,如上图所示。我可以在条目上显示它。我可能对属性使用了错误的术语。
  • 如果你可以发minimal reproducible example 我可以快速浏览一下。像这样玩 20 个问题不是很有效

标签: c# xamarin mvvm


【解决方案1】:

我检查了你的样本,你可以像下面这样修改它。

在 Xaml 中

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

在视图模型中

ObservableCollection默认实现了接口INotifyPropertyChanged。因此,您可以简化 ViewModel 中的代码。

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

 ing.IngredientName = listIngredients[0];

所以 ViewModel 可能会喜欢

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

    }



}

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

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

   //...
}

【讨论】:

  • 对于真实数据,我不知道要将数据硬编码到哪个元素。例如,它可能是 100 种成分中的一种。我想到的唯一其他解决方案是将选定项源和条目绑定在一起。对此有什么想法吗?感谢您的帮助!!!
  • 设置 SelectedIndex 而不是 SelectedItem 似乎有效。仍在检查...
  • 如果使用SelectedIndex ,需要在初始化Picker的ItemSource后设置。
  • 如果对你有帮助别忘了接受我的回答:)
  • 我接受了这个答案,因为它是让我走上正轨的灵感。我的答案是我最后使用的。非常感谢@Lucas Zhang。你太棒了!!!!
【解决方案2】:

目前还不清楚为什么不能像我在不在 ListView 内的选择器中那样直接使用字符串设置 selectedItem。

但是,将选取器设置为使用 SelectedIndex 属性效果很好。这是关键。对于 ListView 的包含选择器,我不会根据 INDEX 而不是 SelectedItem 设置它们的值。

最终代码片段

XAML

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

查看模型

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

        clRecipeIngredient ing = new clRecipeIngredient();

        _downloadedRecipeIngredients.Clear();
        for (int i = 0;i < arryRecipeIngredients.Length;i++)
        {
              
            for (int j=0; j<_listIngredients.Count;j++)
            {
        //FIND THE SELECTED INDEX BASED ON PICKER’S LIST and STORE IN THE CUSTOM CLASS
                if(arryRecipeIngredients[i].IngredientName == _listIngredients[j])
                {
                    arryRecipeIngredients[i].IngredientIDLookedUp = j;
                }
            }

            _downloadedRecipeIngredients.Add(arryRecipeIngredients[i]);

        }

【讨论】:

    猜你喜欢
    • 2020-08-04
    • 2021-06-29
    • 2015-06-01
    • 2014-10-20
    • 2018-03-10
    • 2019-01-25
    • 1970-01-01
    • 2014-08-07
    • 2020-06-19
    相关资源
    最近更新 更多