Search code examples
c#xamarinmvvmdata-bindingprism

Binding SelectedItem on Picker Not Working


I am having trouble setting the selected item in a picker menu. I have a List in my viewModel that I bound the ItemSource to in the view and and that works great, I can select the picker and see my list of facilities but I cannot set the SelectedItem or SelectedItem index to show a default selection. The other data I bind in my view works just fine when i set them in the NavigatedTo() method. I also am getting into the setter for Facility becasue my writeLine is being written in the console. I am successfully getting the sectedItem out of the list when i add it to my parameters in the NavigateFrom() method without any problem i just cant seem to set the value of the picker. Also if the displayAlert is uncommented at the bottom of the NavigateTo() method, I can see that Facility equals a valid object so I know its being set properly but the view doesn't want to display it in the picker?

    <Grid Grid.Row="3" Grid.ColumnSpan="2" Padding="15">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
            <Label Text="Facility:"  VerticalTextAlignment="Center"/>
            <Picker Grid.Column="1" ItemsSource="{Binding FacilityList}" 
                    ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding Facility, Mode=TwoWay" />
    </Grid>
public class CallInfoPageViewModel : ViewModelBase, INavigationAware
    {
        private Facility _facility;
        public Facility Facility
        {
            get { return _facility; }
            set
            {
                Console.WriteLine("\n**************\n we hit the thing!\n************");
                SetProperty(ref _facility, value);
            }
        }

        public List<Facility> FacilityList { get; set; }

        private readonly INavigationService _navigationService;
        private DelegateCommand _showHelpPageCommand;
        public DelegateCommand ShowHelpPageCommand =>
            _showHelpPageCommand ?? (_showHelpPageCommand = new DelegateCommand(ExecuteShowHelpPageCommand));


        public CallInfoPageViewModel(INavigationService navigationService)
        {
            Title = "Call Information";
            _navigationService = navigationService;

            FacilityList = new MockDataStore().GetFacilityList();

            CallDate = SpillDate = DateTime.Now.Date;
            CallTime = DateTime.Now.TimeOfDay;
            SpillTime = CallTime.Subtract(TimeSpan.FromHours(1));
        }

        async void ExecuteShowHelpPageCommand()
        {
            await _navigationService.NavigateAsync("CallInfoHelpPage");
        }

        // called when leaving this view/viewModel
        public async void OnNavigatedFrom(INavigationParameters parameters)
        {
            if (CallerName != null)
            {
                parameters.Add("callerName", CallerName);
            }

            if (UserName != null)
            {
                parameters.Add("userName", UserName);
            }

            if (Facility != null)
            {
                parameters.Add("facility", Facility);
            }

            parameters.Add("callDate", CallDate);
            parameters.Add("callTime", CallTime);
            parameters.Add("spillDate", SpillDate);
            parameters.Add("spillTime", SpillTime);
            parameters.Add("spillStillOngoing", SpillStillOngoing);
            parameters.Add("spillContainedOnSite", SpillContainedOnSite);
            parameters.Add("needAssistance", NeedAssistance);
        }

        // called when everything created/ initialised and page added to navigation stack
        public async void OnNavigatedTo(INavigationParameters parameters)
        {

            if (parameters.ContainsKey("demoMode") || parameters.ContainsKey("callInfoPageComplete"))
            {
                UserName = parameters.GetValue<string>("userName");
                CallerName = parameters.GetValue<string>("callerName");
                SpillDate = parameters.GetValue<DateTime>("spillDate");
                CallDate = parameters.GetValue<DateTime>("callDate");
                SpillTime = parameters.GetValue<TimeSpan>("spillTime");
                CallTime = parameters.GetValue<TimeSpan>("callTime");
                Facility = parameters.GetValue<Facility>("facility");
                SpillStillOngoing = parameters.GetValue<bool>("spillOngoing");
                SpillContainedOnSite = parameters.GetValue<bool>("spillContainedOnSite");
                NeedAssistance = parameters.GetValue<bool>("needAssistance");
            }

            //await Application.Current.MainPage.DisplayAlert("params",
            //    "Facilty " + Facility + "\n name: " + Facility.Name + "\naddr: " + Facility.Address,
            //    "OK");
        }
    }
async void ExecuteLoadDemoCommand()
    {
        loadDemoBool = true;
        report.CallerName = "Stephan Kemper";
        report.UserName = "Tyler Bartlett";
        report.SpillDate = new DateTime(2019, 12, 10);
        report.CallDate = new DateTime(2019, 12, 10);
        report.SpillTime = new TimeSpan(13, 0, 0);
        report.CallTime = new TimeSpan(14, 0, 0);
        report.Facility = new MockDataStore().GetFacility("Millersburg - Main");
        report.SpillStillOngoing = false;
        report.SpillContainedOnSite = true;
        report.NeedAssistance = false;
    }
public Facility GetFacility(string facilityName)
    {
        return facilities.Find(facility => facility.Name == facilityName);
    }

Solution

  • The SelectedItem needs to be a reference to an item that is in your ItemsSource. Not a COPY of the object, a reference to the same object. The fact that you spin up a new MockDataStore() to get Facility makes me think they are not identical references