[英]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; }
我檢查了你的樣本,你可以像下面這樣修改它。
<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.