Hi there,
I will try to explain this as best I can so please bare with me:
Background:
I have two pages that interact with each other - a customer page (CustomerPage) which stores a listing of customers and an edit page (CustomerEditPage) used to add new customers or edit customers passed in from the customer page list. I am able to pass the Customer class of the selected customer in the customer page to the edit customer page without issue. I am also able to set all of the Entry controls to the values through passing the values. In addition to the Entry controls I also have a Picker control used to store location name values (e.g. 123 West St, 85 George St, etc.). It has an ItemSource that loads successfully through the view model. However I have an issue when trying to specify the selected item from a value passed to the view model on load. The bound property fires and shows it being set, but the control does not show anything selected after load in the application. If I click on the control, my values are there but again nothing is selected.
Can someone help me explain how I can set the selected item?
Things I have tried:
- Ensuring the ItemSource is loaded before the SelectedItem value is set
- Put a break-point on the Handles_ItemSelected event to see when it is firing (*Note it only fires when I select an item from the list and NOT when set through code in the view model)
- Adding an ID column to the CustomerLocation class to see if the Picker needed a key value
Item Selected from ListView in CustomerViewModel.cs
ItemSelectedCommand = new Command(async () =>
{
await navigationService.NavigateModelAsync(PageNames.CustomerEditPage, Customer, true, false);
});
This works as expected
Picker Control from CustomerEditPage.xaml
<Picker ItemsSource="{Binding Locations}"
ItemDisplayBinding="{Binding LocationName}"
SelectedItem="{Binding CustLocation, Mode=TwoWay}"
SelectedIndexChanged="Handle_SelectedIndexChanged"/>
*Note that the SelectedIndexChanged was only set so I can see when it was firing
CustomerEditPage.xaml.cs
public CustomerEditPage(CustomerEntry customer)
{
var vm = new ViewModels.CustomerEditViewModel(App.NavigationService);
BindingContext = vm;
if (customer != null || customer.ID > 0)
{
vm.EditCustomer = customer;
vm.SetEditCustomer();
}
InitializeComponent();
}
void Handle_SelectedIndexChanged(object sender, System.EventArgs e)
{
//Testing to see if we get to this break-point
}
As you can see, I take in the CustomerEntry class object. I check if it is not null and has an ID > 0 and if so passes to the ViewModel to set the controls. Again, the Handle_SelectedIndexChange is only fired for testing purposes (using a breakpoint).
CustomerEditViewModel.cs
private CustomerEntry editCustomer;
public CustomerEntry EditCustomer
{
get { return editCustomer; }
set
{
editCustomer = value;
OnPropertyChanged("EditCustomer");
}
}
private ObservableCollection<CustomerLocation> locations = new ObservableCollection<CustomerLocation>();
public ObservableCollection<CustomerLocation> Locations
{
get { return locations; }
set
{
locations = value;
OnPropertyChanged("Locations");
}
}
private CustomerLocation custLocation;
public CustomerLocation CustLocation
{
get { return custLocation; }
set
{
custLocation = value;
OnPropertyChanged("CustLocation");
}
}
public CustomerEditViewModel(INavigationService navigationService)
{
SubmitCommand = new Command(async () =>
{
await OnSubmit();
await navigationService.NavigateModelAsync(PageNames.CustomerPage, null, true, true);
});
CancelCommand = new Command(async () =>
{
await navigationService.GoBack();
});
LoadLocations();
}
public async Task LoadLocations()
{
List<CustomerLocation> loadLocations = await App.Database.GetLocationsAsync();
Locations = new ObservableCollection<CustomerLocation>(loadLocations);
}
public void SetEditCustomer()
{
ID = EditCustomer.ID;
CustomerName = EditCustomer.CustomerName;
CustLocation = new CustomerLocation()
{
LocationName = EditCustomer.LocationName
};
Email = EditCustomer.Email;
Notes = EditCustomer.Notes;
}
The EditCustomer, Locations and CustLocation properties all fire. Properties for ID, CustomerName,Email and Note omitted for brevity.
Locations are loaded from a SQLiteAsyncConnection (database is located on device)
CustomerLocation.cs
public class CustomerLocation
{
public string LocationName { get; set; }
}
As mentioned above, I put a mock ID column in this class (I didn't actually designate it as a key now that I think about it - I am not sure if that makes a difference).
CustomerEntry.cs
public class CustomerEntry
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string CustomerName { get; set; }
public string LocationName { get; set; }
public string Email { get; set; }
public string Notes { get; set; }
public DateTime TimeStamp { get; set; }
}
CustomerEntry class here for reference purposes.