Sam
Sam

Reputation: 30324

FlyoutFooter ContentView with dependency injection in .NET MAUI app

I created a ContentView for the FlyoutFooter in my .NET MAUI app. In the footer, I placed an ImageButton with an icon that the user can use to sign out.

I'm also using dependency injection throughout the app so I registered both the FlyoutFooter view and its corresponding FlyoutFooterViewModel in the DI container.

The problem is when I try to tell the Shell to use the FlyoutFooter content view, it doesn't like it becuase its constructor receives a parameter -- see screen shot below.

enter image description here

The code behind for the FlyoutFooter looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MyApp.ViewModels.Flyout"
             x:Class="MyApp.Views.Flyout.FlyoutFooter"
             x:DataType="vm:FlyoutFooterViewModel">
    <Grid
      RowDefinitions="120"
      ColumnDefinitions="150, 150">
        <Image
            Grid.Row="0"
            Grid.Column="0"
            HorizontalOptions="StartAndExpand"
            Margin="50,0,0,0">
            <Image.Source>
                <FontImageSource
                    FontFamily="MISHRP"
                    Glyph="{StaticResource SettingsIcon}"
                    Color="White"/>
            </Image.Source>
            <Image.GestureRecognizers>
                <TapGestureRecognizer
                    Command="{Binding GotoSettingsCommand}" />
            </Image.GestureRecognizers>
        </Image>
        <Image
            Grid.Row="0"
            Grid.Column="1"
            HorizontalOptions="EndAndExpand"
            Margin="0,0,30,0">
            <Image.Source>
                <FontImageSource
                    FontFamily="MISHRP"
                    Glyph="{StaticResource PowerIcon}"
                    Color="White"/>
            </Image.Source>
            <Image.GestureRecognizers>
                <TapGestureRecognizer
                    Command="{Binding SignOffCommand}"/>
            </Image.GestureRecognizers>
        </Image>
    </Grid>
</ContentView>

In the code behind for FlyoutFooter.xaml, I inject the view model -- see below:

public partial class FlyoutFooter : ContentView
{

    FlyoutFooterViewModel _vm;
    public FlyoutFooter(FlyoutFooterViewModel vm)
    {
        InitializeComponent();
        _vm = vm;
        BindingContext = _vm;
    }
}

The view model looks like this:

public class FlyoutFooterViewModel : BaseViewModel
{
   IDatabaseService _dbService;

   public ICommand GotoSettingsCommand { get; }
   public ICommand SignOffCommand { get; }

   public FlyoutFooterViewModel(IDatabaseService dbService)
   {
      _dbService = dbService;

      GotoSettingsCommand = new AsyncRelayCommand(GotoSettings);
      SignOffCommand = new AsyncRelayCommand(SignOff);
   }

   async Task GotoSettings()
   {
      // Send user to Settings page
   }

   async Task SignOff()
   {
      SecureStorage.Remove("access_token");

      await _dbService.ClearAll();

      await Shell.Current.GoToAsync($"///{nameof(Login)}");
   }
}

Any suggestions for handling this scenario?

Upvotes: 2

Views: 1698

Answers (1)

AC Thompson
AC Thompson

Reputation: 340

I just figured out a way to do this. Instead of the control with a view model, I gave AppShell a view model so I can use FlyoutFooterTemplate.

<Shell.FlyoutFooterTemplate>
    <DataTemplate>
        <Label Text="{Binding DABUser.Name}" BackgroundColor="Red"/>
    </DataTemplate>
</Shell.FlyoutFooterTemplate>

I inject IServiceProvider into AppShell

public AppShell(IServiceProvider serviceProvider)

and then set the BindingContext to the view model I want

BindingContext = serviceProvider.GetService<FlyoutFtViewModel>()

As I type this out, I am going inject the viewmodel into the constructor instead.

Upvotes: 1

Related Questions