簡體   English   中英

嘗試在 listview MVVM Xamarin 中設置選擇器

[英]Trying to set picker within listview MVVM Xamarin

嘗試通過使用 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>

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

    }



}

在此處輸入圖像描述

cl食譜成分

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

我檢查了你的樣本,你可以像下面這樣修改它。

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

    }



}

並且不要忘記在 model 中實現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");
            }
        }
    }

   //...
}

在此處輸入圖像描述

仍然不清楚為什么你不能像我在不在 ListView 內的選擇器中那樣直接使用字符串設置 selectedItem。

但是,將選取器設置為使用 SelectedIndex 屬性效果很好。 這是關鍵。 對於 ListView 包含的選擇器,我不會根據 INDEX 而不是 SelectedItem 設置它們的值。

最終代碼片段

XAML

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

查看 Model

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

        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM