I have Index Page, which opens up when the App starts. In Index Page there is an Icon called Setting, by clicking it, Settings Page opens up and from there user can Navigate to 'Connections', 'Credentials', 'Proofs' page.
But the problem is that when I navigate to any of these three pages, I can only see the Views and the ViewModel isn't loading e.g. I can see the output of Views Page code but not of the ViewModel.
App.xml.cs
public App() { InitializeComponent(); } protected override async void OnStart() { await Host.StartAsync(); // View models and pages mappings var _navigationService = Container.Resolve<INavigationService>(); _navigationService.AddPageViewModelBinding<MainViewModel, MainPage>(); _navigationService.AddPageViewModelBinding<ConnectionsViewModel, ConnectionsPage>(); _navigationService.AddPageViewModelBinding<ConnectionViewModel, ConnectionPage>(); _navigationService.AddPageViewModelBinding<RegisterViewModel, RegisterPage>(); _navigationService.AddPageViewModelBinding<AcceptInviteViewModel, AcceptInvitePage>(); _navigationService.AddPageViewModelBinding<CredentialsViewModel, CredentialsPage>(); _navigationService.AddPageViewModelBinding<CredentialViewModel, CredentialPage>(); _navigationService.AddPageViewModelBinding<ProofsViewModel, ProofsPage>(); _navigationService.AddPageViewModelBinding<ProofViewModel, ProofPage>(); _navigationService.AddPageViewModelBinding<CreateInvitationViewModel, CreateInvitationPage>(); if (Preferences.Get(AppConstant.LocalWalletProvisioned, false)) { await _navigationService.NavigateToAsync<MainViewModel>(); } else { await _navigationService.NavigateToAsync<RegisterViewModel>(); } timer.Enabled = true; }
INavigationService.cs
using System; using System.Collections.Generic; using System.Threading.Tasks; using Xamarin.Forms; namespace Osma.Mobile.App.Services.Interfaces { public interface INavigationService { Task PopModalAsync(); Task NavigateToAsync(Page page, NavigationType type = NavigationType.Normal); Task NavigateToAsync<TViewModel>(object parameter = null, NavigationType type = NavigationType.Normal) where TViewModel : IABaseViewModel; Task NavigateToAsync<TViewModel>(TViewModel viewModel, object parameter = null, NavigationType type = NavigationType.Normal) where TViewModel : IABaseViewModel; Task AddTabChildToMainView<TViewModel>(TViewModel viewModel, object parameter, int atIndex = -1) where TViewModel : IABaseViewModel; Task NavigateBackAsync(); Task RemoveLastFromBackStackAsync(); Task NavigateToPopupAsync<TViewModel>(bool animate, TViewModel viewModel) where TViewModel : IABaseViewModel; Task NavigateToPopupAsync<TViewModel>(object parameter, bool animate, TViewModel viewModel) where TViewModel : IABaseViewModel; Task CloseAllPopupsAsync(); IList<IABaseViewModel> GetMainViewTabChildren(); bool RemoveTabChildFromMainView(IABaseViewModel childViewModel); void SetCurrentTabOnMainView<TViewModel>(); Type GetCurrentPageViewModel(); bool SetCurrentPageTitle(string title); void AddPageViewModelBinding<TVm, TP>(); void AddPopupViewModelBinding<TVm, TV>(); } }
If I make the Connections/Credentials/Proof page to be the first page to open up when the App starts, then the ViewModel is loading..
MainPage.xml
<?xml version="1.0" encoding="utf-8" ?> <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:index="clr-namespace:Osma.Mobile.App.Views.Index;assembly=Osma.Mobile.App" xmlns:settings="clr-namespace:Osma.Mobile.App.Views.Settings;assembly=Osma.Mobile.App" xmlns:connections="clr-namespace:Osma.Mobile.App.Views.Connections;assembly=Osma.Mobile.App" xmlns:credentials="clr-namespace:Osma.Mobile.App.Views.Credentials;assembly=Osma.Mobile.App" xmlns:proofs="clr-namespace:Osma.Mobile.App.Views.Proof;assembly=Osma.Mobile.App" xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" x:Class="Osma.Mobile.App.Views.MainPage" BackgroundColor="#004B86" NavigationPage.HasNavigationBar="False" BarBackgroundColor ="#004B86" BarTextColor="#004B86" SelectedTabColor="#004B86" UnselectedTabColor="#004B86" Title="Prove" CurrentPageChanged="CurrentPageChanged" Appearing="Appearing"> <index:IndexPage BindingContext="{Binding Index}"> </index:IndexPage> <settings:SettingsPage BindingContext="{Binding Settings}"> </settings:SettingsPage> <connections:ConnectionsPage BindingContext="{Binding Connections}"> </connections:ConnectionsPage> <credentials:CredentialsPage BindingContext="{Binding Credentials}"> </credentials:CredentialsPage> <proofs:ProofsPage BindingContext="{Binding Proof}"> </proofs:ProofsPage> </TabbedPage>
MainPage.xml.cs
using Osma.Mobile.App.ViewModels; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace Osma.Mobile.App.Views { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainPage : TabbedPage, IRootView { public MainPage () { InitializeComponent (); } private new void CurrentPageChanged(object sender, System.EventArgs e) => Title = GetPageName(CurrentPage); private new void Appearing(object sender, System.EventArgs e) => Title = GetPageName(CurrentPage); private string GetPageName(Page page) { if (page.BindingContext is ABaseViewModel vmBase) return vmBase.Name; return null; } } }
MainViewModel.cs
using System.Threading.Tasks; using Acr.UserDialogs; using Osma.Mobile.App.Services.Interfaces; using Osma.Mobile.App.ViewModels.Connections; using Osma.Mobile.App.ViewModels.CreateInvitation; using Osma.Mobile.App.ViewModels.Credentials; using Osma.Mobile.App.ViewModels.Proof; using ReactiveUI; namespace Osma.Mobile.App.ViewModels { public class MainViewModel : ABaseViewModel { public MainViewModel( IUserDialogs userDialogs, INavigationService navigationService, ConnectionsViewModel connectionsViewModel, CredentialsViewModel credentialsViewModel, ProofsViewModel proofsViewModel, CreateInvitationViewModel createInvitationViewModel ) : base( nameof(MainViewModel), userDialogs, navigationService ) { Connections = connectionsViewModel; Credentials = credentialsViewModel; Proof = proofsViewModel; CreateInvitation = createInvitationViewModel; } public override async Task InitializeAsync(object navigationData) { await Connections.InitializeAsync(null); await Credentials.InitializeAsync(null); await Proof.InitializeAsync(null); await CreateInvitation.InitializeAsync(null); await base.InitializeAsync(navigationData); } #region Bindable Properties private ConnectionsViewModel _connections; public ConnectionsViewModel Connections { get => _connections; set => this.RaiseAndSetIfChanged(ref _connections, value); } private CredentialsViewModel _credentials; public CredentialsViewModel Credentials { get => _credentials; set => this.RaiseAndSetIfChanged(ref _credentials, value); } private ProofsViewModel _proof; public ProofsViewModel Proof { get => _proof; set => this.RaiseAndSetIfChanged(ref _proof, value); } private CreateInvitationViewModel _createInvitation; public CreateInvitationViewModel CreateInvitation { get => _createInvitation; set => this.RaiseAndSetIfChanged(ref _createInvitation, value); } #endregion } }
ConnectionsViewModel.cs
using Osma.Mobile.App.Events; using Osma.Mobile.App.Extensions; using Osma.Mobile.App.Services; using Osma.Mobile.App.Services.Interfaces; using Osma.Mobile.App.Utilities; using Osma.Mobile.App.ViewModels.CreateInvitation; ... ... namespace Osma.Mobile.App.ViewModels.Connections { public class ConnectionsViewModel : ABaseViewModel { private readonly IConnectionService _connectionService; private readonly IMessageService _messageService; private readonly IAgentProvider _agentContextProvider; private readonly IEventAggregator _eventAggregator; private readonly ILifetimeScope _scope; public ConnectionsViewModel(IUserDialogs userDialogs, INavigationService navigationService, IConnectionService connectionService, IMessageService messageService, IAgentProvider agentContextProvider, IEventAggregator eventAggregator, ILifetimeScope scope) : base("Connections", userDialogs, navigationService) { _connectionService = connectionService; _messageService = messageService; _agentContextProvider = agentContextProvider; _eventAggregator = eventAggregator; _scope = scope; } public override async Task InitializeAsync(object navigationData) { await RefreshConnections(); _eventAggregator.GetEventByType<ApplicationEvent>() .Where(_ => _.Type == ApplicationEventType.ConnectionsUpdated) .Subscribe(async _ => await RefreshConnections()); await base.InitializeAsync(navigationData); } ..... ..... } }
ConnectionsPage.xml
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:components="clr-namespace:Osma.Mobile.App.Views.Components;assembly=Osma.Mobile.App" xmlns:converters="clr-namespace:Osma.Mobile.App.Converters;assembly=Osma.Mobile.App" xmlns:behaviours="clr-namespace:Osma.Mobile.App.Behaviors;assembly=Osma.Mobile.App" x:Class="Osma.Mobile.App.Views.Connections.ConnectionsPage" Title="Connections"> <ContentPage.Resources> <ResourceDictionary> <converters:SelecteditemEventArgsToSelectedItemConverter x:Key="SelectedItemConverter" /> <converters:InverseBooleanConverter x:Key="BooleanInverse" /> </ResourceDictionary> </ContentPage.Resources> <!-- <ContentPage.ToolbarItems> <ToolbarItem Name="Add Connection" Order="Primary" Text="Connect" Priority="0" Command ="{Binding ScanInviteCommand}"/> <ToolbarItem Name="CreateInvitation" Order="Secondary" Text="Create Invitation" ios:NavigationPage.PrefersLargeTitles="true" Priority="0" Command ="{Binding CreateInvitationCommand}"/> </ContentPage.ToolbarItems> --> <ContentPage.Content> <StackLayout> <StackLayout IsVisible="{Binding HasConnections}"> <ListView ... ... ... </ListView> </StackLayout> <StackLayout VerticalOptions="FillAndExpand" IsVisible="{Binding HasConnections, Converter={StaticResource BooleanInverse}}"> <StackLayout Orientation="Vertical" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"> <ActivityIndicator IsVisible="{Binding RefreshingConnections}" IsRunning="{Binding RefreshingConnections}"/> <Label HorizontalOptions="CenterAndExpand" HorizontalTextAlignment="Center" IsVisible="{Binding RefreshingConnections, Converter={StaticResource BooleanInverse}}" Text="You have no connections - Click connect to get started" TextColor="White"/> </StackLayout> </StackLayout> </StackLayout> </ContentPage.Content> </ContentPage>
SettingsPage.xml
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:forms="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms" xmlns:views="clr-namespace:Osma.Mobile.App.Views.Settings;assembly=Osma.Mobile.App" xmlns:converters="clr-namespace:Osma.Mobile.App.Converters;assembly=Osma.Mobile.App" x:Class="Osma.Mobile.App.Views.Settings.SettingsPage" NavigationPage.HasNavigationBar="False" BackgroundColor="#004B86"> <ContentPage.Content> <Grid> <Grid.RowDefinitions> <RowDefinition Height="70" /> <RowDefinition Height="50" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <ImageButton Source="drawable/BackArrow.png" WidthRequest = "30" HeightRequest = "30" MinimumHeightRequest = "15" MinimumWidthRequest = "15" BackgroundColor="#004B86" VerticalOptions="Start" HorizontalOptions="Start" Padding="0" Margin="10,10,0,0" Clicked="IndexPage" /> <Label FontSize="20" HorizontalOptions="Start" Text="Settings" TextColor="White" VerticalOptions="Start" Margin="60,10,0,0"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding IndexPageCommand}" /> </Label.GestureRecognizers> </Label> </Grid> <Grid Grid.Row="1"> <BoxView Color="#004B79" /> <ImageButton Source="drawable/connection_icon.png" WidthRequest = "30" HeightRequest = "30" MinimumHeightRequest = "15" MinimumWidthRequest = "15" BackgroundColor="#004B86" VerticalOptions="Start" HorizontalOptions="Start" Padding="0" Margin="10,10,0,0" Clicked="ConnectionsPage" /> <Label FontSize="20" HorizontalOptions="Start" Text="Connections" TextColor="White" VerticalOptions="Start" Margin="60,10,0,0"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding ConnectionsPageCommand}" /> </Label.GestureRecognizers> </Label> </Grid> </Grid> </ContentPage.Content> </ContentPage>
SettingsPage.xml.cs
using System; using System.Windows.Input; using System.Threading.Tasks; using Xamarin.Forms; using Osma.Mobile.App.Views.Index; using Osma.Mobile.App.Views.Connections; namespace Osma.Mobile.App.Views.Settings { public partial class SettingsPage : ContentPage { public SettingsPage() { InitializeComponent(); BindingContext = this; } public async Task IndexPageNavigate() { await Navigation.PushAsync(new IndexPage()); } public async Task ConnectionsPageNavigate() { await Navigation.PushAsync(new ConnectionsPage()); } #region Bindable Command public ICommand IndexPageCommand => new Command(async () => await IndexPageNavigate()); public ICommand ConnectionsPageCommand => new Command(async () => await ConnectionsPageNavigate()); #endregion private async void IndexPage(object sender, System.EventArgs e) { await Navigation.PushAsync(new IndexPage()); } private async void ConnectionsPage(object sender, System.EventArgs e) { await Navigation.PushAsync(new ConnectionsPage()); } } }