Below is a link to a sample program using Visual Studio 2017 v15.8.2 and Xamarin Forms v3.1.
The app displays one page that has a ListView with a custom cell that displays a couple of text fields
and a Picker. The Picker does not show the selected values in Android. It works as expected in UWP
(pre-populated picker value is displayed and selected picker values are also displayed)
[Edit] When The Droid page loads, the debug statements indicate that the SelectedIndex in each Cell has the right value and then, after OnAppearing the SelectedIndex(s) get changed to -1 so the Pickers show blank. Also, when a Picker has a value selected, it displays briefly and then gets replaced by a blank.
[/Edit]
The data required by the Listview is hard coded. To run this, all you need is to download it,
open it in the correct version of Visual Studio with Xamarin Forms and run it in either Android or UWP.
(Note: I have not tested this version in iOS, however in my original that is part of my active
development, the iOS version works as expected)
https://bitbucket.org/WillAutio/filelist/src/master/
And here are the relevant snippets of code. From the XAML:
`
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Vertical" Margin="0,0,0,15" BackgroundColor="Green">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding reportID}" FontSize="18" BackgroundColor="White" TextColor="Black"
MinimumWidthRequest="40"/>
<Label Text="{Binding question}" FontSize="18" BackgroundColor="White" TextColor="Black"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Picker x:Name="AnsPicker"
TextColor="Black" BackgroundColor="Yellow" ItemsSource="{Binding AnswerList}"
HeightRequest="50" WidthRequest="150"
SelectedIndex="{Binding Selected, Mode=TwoWay}"
SelectedIndexChanged="OnAnswerPicker_Changed" />
</StackLayout>
<StackLayout Orientation="Vertical" Margin="0,0,0,0" BackgroundColor="Black" >
<Entry x:Name="Explanation" Text="{Binding explanation , Mode=TwoWay}"
FontSize="18" BackgroundColor="White"
TextColor="Black" Placeholder="Explanation" Margin="0,1,0,5"
MinimumWidthRequest="200" TextChanged="Entry_TextChanged" />
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>`
From the code behind:
`
public partial class MainPage : ContentPage
{
MainPageViewModel MPVM { get; set; }
public MainPage()
{
InitializeComponent();
MPVM = new MainPageViewModel();
this.BindingContext = MPVM;
MyLV.ItemsSource = MPVM.MPM.ocMC;
}
protected override void OnAppearing()
{
base.OnAppearing();
}
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
// doesn't matter what goes in here
}
private void OnAnswerPicker_Changed(object sender, ToggledEventArgs e)
{
Picker picker = sender as Picker;
MyClass item = (MyClass)((Picker)sender).BindingContext;
Debug.WriteLine("\n item " + item.ToString());
Debug.WriteLine("\n MTVM.MTM.ocMC[item.reportID - 1] " + MPVM.MPM.ocMC[item.reportID - 1].ToString());
MPVM.MPM.ocMC[item.reportID - 1].yesno = item.yesno;
MPVM.MPM.ocMC[item.reportID - 1].Selected = item.Selected;
Debug.WriteLine("\n MTVM.MTM.ocMC[item.reportID - 1] " + MPVM.MPM.ocMC[item.reportID - 1].ToString());
Debug.WriteLine("\n ");
}
}
`
And MyClass:
`
public class MyClass : ObservableObject
{
public int? myKey { get; set; } // local primary key
public int reportID { get; set; } //
public bool? _yesno;
public bool? yesno // null => None; true => Yes; false => No;
{
get
{
return this._yesno;
}
set
{
if (_yesno != value)
{
_yesno = value;
OnPropertyChanged("yesno");
}
}
}
//public string explanation { get; set; }
private string _explanation;
public string explanation
{
get
{
return this._explanation;
}
set
{
if (_explanation != value)
{
if (_explanation == null && value == "")
{ // _explanation starts out as a null. The constructor sets it to "".
// That triggers a change that we do not care about.
_explanation = value;
}
else
{
_explanation = value;
toupload = 1; // on change to explanation mark this record for upload
OnPropertyChanged("explanation");
}
}
}
}
//public string prjnum { get; set; }
public long projectID { get; set; }
public int toupload { get; set; } // 1 means the record needs to be uploaded
public bool ShowToggle { get; set; }
private bool _answerToggle;
public bool AnswerToggle
{
get
{
return this._answerToggle;
}
set
{
if (_answerToggle != value)
{
_answerToggle = value;
toupload = 1; // on change to AnswerToggle mark this record for upload
OnPropertyChanged("AnswerToggle");
}
}
}
public ObservableCollection<string> AnswerList { get; set; }
public int _selected;
public int Selected
{
get
{
return this._selected;
}
set
{
if (_selected != value)
{
_selected = value;
toupload = 1; // on change to AnswerToggle mark this record for upload
if (_selected == 0)
{
yesno = null;
}
else if (_selected == 1)
{
yesno = true;
}
else if (_selected == 2)
{
yesno = false;
}
OnPropertyChanged("Selected");
}
}
}
public string question { get; set; }
public MyClass()
{
AnswerList = new ObservableCollection<string>();
AnswerList.Add("None");
AnswerList.Add("Yes");
AnswerList.Add("No");
}
public override string ToString()
{
string ans =
" yesno =" + yesno +
" Selected =" + Selected +
" myKey =" + myKey +
" reportID =" + reportID +
" toupload =" + toupload +
" projectID =" + projectID +
" question =" + question;
return ans;
}
}
`