Search code examples
c#mvvmxamarin.formsmvvmcross

mvvmcross navigate to viewmodel from tabbed


I have a Xamarin Forms application using mvvmcross. There I have navigation via TabbedPages. Each page has a xaml + code behind and viewmodel.

Relevant code for first page:

<?xml version="1.0" encoding="utf-8" ?>
<pages:BaseTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:pages="clr-namespace:ABBI_XPlat_3.Pages;assembly=ABBI_XPlat_3"
         x:Class="ABBI_XPlat_3.Pages.DeviceListPage"
         Title="Discover devices"
         x:Name="DevicePage">
<pages:BaseTabbedPage.Resources>
  <ResourceDictionary>
     <DataTemplate x:Key="DeviceItemTemplate"> ... </DataTemplate>
  </ResourceDictionary>
</pages:BaseTabbedPage.Resources>
<pages:BaseTabbedPage.Children>
  <pages:BasePage Title="Scan for devices">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
      </Grid.RowDefinitions>
      <StackLayout BackgroundColor="#FF6969" Padding="10" IsVisible="{Binding IsStateOn, Converter={StaticResource InverseBoolean}}">
        <Label Text="{Binding StateText}" FontSize="18" HorizontalTextAlignment="Center"></Label>
        </StackLayout>

      <ListView Grid.Row="1" ItemsSource="{Binding Devices}" SelectedItem="{Binding SelectedDevice, Mode=TwoWay}"
             IsPullToRefreshEnabled="True"
             RefreshCommand="{Binding RefreshCommand}"
             IsRefreshing="{Binding IsRefreshing, Mode=OneWay}"
             RowHeight="80"
             ItemTemplate="{StaticResource DeviceItemTemplate}">
      </ListView>

      <StackLayout Grid.Row="2" Orientation="Horizontal">
        <Button Text="Connect" Command="{Binding ConnectToSelectedCommand}" HorizontalOptions="FillAndExpand"/>
        <Button Text="Stop Scan" Command="{Binding StopScanCommand}" HorizontalOptions="End"/>
        <ActivityIndicator IsRunning="{Binding IsRefreshing}"
                         HeightRequest="24"
                         WidthRequest="24"
                         VerticalOptions="Center"
                         HorizontalOptions="End"/>
      </StackLayout>

    </Grid>
  </pages:BasePage>
  <pages:ServiceListPage Title="Services"/>
  <pages:OtherTabbedPage Title="Services"/>
</pages:BaseTabbedPage.Children>
</pages:BaseTabbedPage>

I am able to call different viewmodels from buttons in my main view model using:

public MvxCommand ConnectToSelectedCommand => new MvxCommand(ConnectToSelectedDeviceAsync, CanDisplayServices);

    private async void ConnectToSelectedDeviceAsync()
    {
        ShowViewModel<ServiceListViewModel>(new MvxBundle(new Dictionary<string, string> { { DeviceIdKey, SystemDevices.FirstOrDefault().Id.ToString() } }));
    }

within my main ViewModel. But I want to be able to use the tabs to navigate between ViewModels. At the moment if I click on a tab, then it brings up the page, but without the associated ViewModel.

Help please!


Solution

  • Finally managed to solve the problem. It was so simple that I could not find an answer anywhere. I just had to add a bindingcontext to the codebehind of the page.

    public ServiceListPage()
        {
            InitializeComponent();
            this.BindingContext = new ViewModels.ServiceListViewModel(Plugin.BLE.CrossBluetoothLE.Current.Adapter, UserDialogs.Instance);
        }