Reputation: 1486
I try using mvvm in my xamarin forms but i'm still litle bit confused with the navigation in each page, I Already Create Interface and NavigationService to handle all Navigation in my Xamarin Forms, there is no error code line but when i click the buton and try to navigate to other page it always crash. Here is some of my code My Interface
namespace KGVC.Interfaces
{
public interface INavigationService
{
void NavigateToDashboard();
void NavigateToLogout();
void NavigateBack();
void gotoNews();
void goEvent();
void gotoKGCash();
void gotoCardCommnunity();
void gotoSetting();
void gotoNearbyLocation();
}
}
my navigationservice
namespace KGVC.Services
{
public class NavigationService : INavigationService
{
public void goEvent()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new EventPage());
}
public void gotoCardCommnunity()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new CardCommunityPage());
}
public void gotoKGCash()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new KGCashPage());
}
public void gotoNearbyLocation()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new StoreMaps());
}
public void gotoNews()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new RssFeedView());
}
public void gotoSetting()
{
var currentPage = GetCurrentPage();
currentPage.Navigation.PushAsync(new SettingPages());
}
public void NavigateBack()
{
throw new NotImplementedException();
}
public void NavigateToDashboard()
{
var currentPage = GetCurrentPage();
Application.Current.MainPage = new MainPage();
}
public void NavigateToLogout()
{
var currentPage = GetCurrentPage();
Application.Current.MainPage = new NewPageLogin();
}
private Page GetCurrentPage()
{
var currentPage = Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
return currentPage;
}
}
}
my view model
public class GridMenuViewModel
{
public ICommand gotoNews { get; private set; }
public ICommand goEvent { get; private set; }
public ICommand gotoKGCash { get; private set; }
public ICommand gotoSetting { get; private set; }
public ICommand gotoNearbyLocation { get; private set; }
public GridMenuViewModel()
{
gotoNews = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoNews();
});
goEvent = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.goEvent();
});
gotoKGCash = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoKGCash();
});
gotoSetting = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoSetting();
});
gotoNearbyLocation = new Command(() =>
{
var navigationService = new NavigationService();
navigationService.gotoNearbyLocation();
});
}
}
And my view
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
NavigationPage.HasNavigationBar="True"
NavigationPage.BackButtonTitle="False"
BindingContext="{Binding GridMenuViewModel, Source={StaticResource Locator}}"
xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
xmlns:local="clr-namespace:KGVC.Views.MainPages"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KGVC.Views.MainPages.GridMenu"
Title="HOME"
>
<ContentPage.Content>
<StackLayout >
<StackLayout BackgroundColor="##CEB053">
<StackLayout HeightRequest="35" BackgroundColor="##CEB053" Orientation="Horizontal">
<Label FontAttributes="Italic" TextColor="Black" Margin="9" Text="Hello," FontSize="15"/>
<Label TextColor="Black" Margin="9" Text="John Doe" FontSize="15" FontAttributes="Bold"/>
</StackLayout>
<StackLayout Padding="0" HeightRequest="30" BackgroundColor="#E3E6E3" Orientation="Horizontal">
<Image Margin="5" Source="ic_logo.png"/>
<Label Text="Points" Margin="5" FontSize="13" TextColor="Black"/>
</StackLayout>
</StackLayout>
<StackLayout HeightRequest="220" VerticalOptions="StartAndExpand">
<control:CarouselView HeightRequest="185" ItemsSource="{Binding MyDataSource}" Position="{Binding Position, Mode=TwoWay}">
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Image}"/>
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>
<local:CarouselIndicators IndicatorHeight="9" IndicatorWidth="9" UnselectedIndicator="unselected_circle.png" SelectedIndicator="selected_circle.png" Position="{Binding Position}" ItemsSource="{Binding MyDataSource}" />
</StackLayout>
<ScrollView IsClippedToBounds="True" VerticalOptions="StartAndExpand" Orientation="Vertical" >
<Grid x:Name="controlGrid" VerticalOptions="StartAndExpand" HeightRequest="370" Margin="15">
<Grid.RowDefinitions>
<RowDefinition Height="0" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="110" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="0" >
<Button Image="ic_account.png" Margin="5"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="MY ACCOUNT" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoCardCommunity}" Image="ic_card.png"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="CARD" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="2">
<Button Margin="5" Command="{Binding goEvent}" Image="ic_event"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="PROMO" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Grid.Row="2" Grid.Column="0" Orientation="Vertical">
<Button Margin="5" Command="{Binding gotoNearbyLocation}" Image="ic_store"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="STORE LOCATIONS" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="2" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoNews}" Image="ic_news"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="NEWS" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Grid.Row="2" Grid.Column="2" Orientation="Vertical">
<Button Margin="5" Command="{Binding gotoKGCash}" Image="ic_kgcash"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="E-WALLET" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="0">
<Button Margin="5" Image="ic_ecommerce"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="E-COMMERCE" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="1">
<Button Margin="5" Command="{Binding gotoSetting}" Image="ic_pointsummary.png"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="POINT SUMMARY" HorizontalOptions="Center"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="3" Grid.Column="2">
<Button Margin="5" Command="{Binding gotoSetting}" Image="ic_setting"
Style="{StaticResource plainButton}" />
<Label FontSize="12" Text="SETTINGS" HorizontalOptions="Center"/>
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
i already try change the navigation service to use pushmodalasync, make the navigation async but still crash, Anyone can help me ? and i'm not using prism , mvvmlight and other 3rd party mvvm nuget
Upvotes: 1
Views: 1833
Reputation: 12179
It depends on your MainPage
. Did you check if GetCurrentPage()
actually returns something?
Try to change the GetCurrentPage()
to:
Page GetCurrentPage() =>
Application.Current.MainPage.Navigation?.NavigationStack?.LastOrDefault() ??
Application.Current.MainPage;
Another problems that I spotted:
1. C# naming conventions are different from Java. Method names should start with a capital letter. Currently you have a pure mix.
2. Initialising the BindingContext
in XAML the way you did will create the ViewModel
twice due to a bug. Change it to:
<ContentPage
xmlns:vm="your-namespace.vm"
...>
<ContentPage.BindingContext>
<vm:GridMenuViewModel />
</ContentPage.BindingContext>
</ContentPage>
3. No need to recreate the NavigationService for each command. Reuse it in your ViewModel.
4. You have some corrupted XAML:
<StackLayout BackgroundColor="##CEB053">
Fix the hex code. Generally speaking you could enable XAMLC so you would get notified about XAML errors while building your code.
5. In order to use PushAsync
your MainPage
should be wrapped by NavigationPage
.
6. You need to await async code execution:
public async Task GoToCardCommnunity()
{
var currentPage = GetCurrentPage();
await currentPage.Navigation.PushAsync(new CardCommunityPage());
}
Check over the list above and pay attention to the application output and exceptions.
Upvotes: 1