Reputation: 2300
I am creating a multi-page Xamarin application that allows the user to login in and view locations against that user.
I am able to show the login screen, the user can login via calls to a local database however when I try and use Navigation.PushAsync
to go to the next page, although hitting the constructor for the next page, nothing seems to happen.
I believe it may have something to do with this section of code here.
Login.xaml.cs
public Login()
{
_Login login = new _Login();
this.BindingContext = login;
InitializeComponent();
}
I've set the Login
page as my Main page in App.xaml.cs
however in the constructor I set the binding context to a class called _login. This class gets and sets the email and password for the user when they login and calls off to an external solution to access the sql database. (This all works correctly).
On the login
button such as this:
Login.xaml
<Button Command="{Binding SubmitCommand}"
Text="Login"
FontAttributes="Bold"
FontSize="Large"></Button>
Which when clicked calls off to the SubmitCommand
function as seen below:
_login.cs
public async void OnSubmit()
{
SignInResponse response = await _clientBl.SignInAsync(Email, Password);
Login login = new Login();
if(response.WasSuccessful == true)
{
login.LoginSuccessful(response.User);
}
else
{
// Show error alert
}
}
Which, if successful, calls a function in Login.xaml.cs
public async void LoginSuccessful(ApplicationUser user)
{
// Go to home page
await Navigation.PushAsync(new MainPage
{
BindingContext = user
});
}
which simply pushes a new page and sets the binding context to that of the user. The code hits the constructor in MainPage.xaml.cs however the page is never loaded up. The MainPage contains a stacklayout with a list view
<StackLayout>
<ListView ItemsSource="{Binding Locations}"
ItemSelected="Locations_ItemSelected"
x:Name="listView">
<ListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32">
<On Platform="iOS">100</On>
<On Platform="Android">100</On>
</OnPlatform>
</ListView.RowHeight>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}"
Aspect="AspectFill" Grid.ColumnSpan="2"></Image>
<Label Margin="5"
Text="{Binding Name}"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start"
Grid.Row="0"
Grid.Column="0"
TextColor="White"
FontSize="25"></Label>
<Label Text="{Binding LocationID}"
IsVisible="False"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
which is populated through overriding the OnAppear()
function. Could the issue be that I am sending this page an ApplicationUser
and it is trying to bind the properties in that page to that class?
I did try and replacing the Navigation.PushAsync
with await Navigation.PushAsync(new MainPage());
however it still doesn't show the next page.
Upvotes: 1
Views: 1412
Reputation: 403
For my case this happened because I accidentally had pushed the Login page as Modal on the navigation stack. On that (modal) Login Page I had a "register" button which triggered an pushAsync on the Navigation Stack. The Page "didn't show" although i saw its on the navigation stack in debug because the modal was still above it.
The Solution in that case was to simply not push the Login Page as Modal on the Navigation stack.
Upvotes: 0
Reputation: 89082
here you are creating a NEW instance of the Login page. You want to use the EXISITNG instance that is already being displayed to the user
Login login = new Login();
if(response.WasSuccessful == true)
{
login.LoginSuccessful(response.User);
there are a lot of different ways to approach this, but the simplest is probably
var login = (Login)Application.Current.MainPage;
if(response.WasSuccessful == true)
{
login.LoginSuccessful(response.User);
or if your MainPage
is a NavigationPage
var nav = (NavigationPage)Application.Current.MainPage;
var login = (Login)nav.CurrentPage;
Upvotes: 2
Reputation: 5099
Most likely from the behavior you are describing (and looking at your code), it sounds like it's because the PushAsync is not being run on the UI thread, and this causes the app to load the page on a separate thread. So your app is probably, it's just launching the page on a different thread.
Try to change it to the following:
Device.BeginInvokeOnMainThread(() =>
{
Navigation.PushAsync(new MainPage
{
BindingContext = user
});
});
Let me know if that makes sense.
Upvotes: 0