8

I'm new to .Net Maui but have completed James Montemagno's 4 hour Workshop. Included in the Workshop was:

  1. Creating a Page with a CollectionView
  2. Creating a ViewModel
  3. Creating an async method which calls a data service to retrieve data
  4. Configuring the async method as a ICommand
  5. Binding the data model list to the CollectionView
  6. Binding the Command to a Button

Clicking the button works and populates the CollectionView. How would I go about removing the button and performing this action when the page opens? Note I tried modifying the method by removing the "[ICommand]" which did not work. Also, should this action be done in the Code Behind or in the ViewModel?

Thanks in advance for assistance!

(ModelView)

public partial class FieldAssignedWbsViewModel : BaseViewModel

{
FieldAssignedWbsService fieldAssignedWbsService;
public ObservableCollection<FieldAssignedWbs> WbsList { get; set; } = new();

public FieldAssignedWbsViewModel(FieldAssignedWbsService fieldAssignedWbsService)
{
    Title = "Wbs Assigned";
    this.fieldAssignedWbsService = fieldAssignedWbsService;
}

[ICommand]
async Task GetFieldAssignedWbsListAsync()
{
    if (IsBusy)
        return;
    try
    {
        IsBusy = true;

        var wbsList = await fieldAssignedWbsService.GetFieldAssignedWbsList();

        if (WbsList.Count != 0)
            WbsList.Clear();

        foreach (var wbs in wbsList)
            WbsList.Add(wbs);
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex);
        await Shell.Current.DisplayAlert("Error!",
            $"Undable to get monkeys: {ex.Message}", "OK");
    }
    finally
    {
        IsBusy = false;
    }
}

}

(CollectionView Binding)

<CollectionView BackgroundColor="Transparent"
                    ItemsSource="{Binding WbsList}"
                    SelectionMode="None">

(Code behind page with incorrect call to Command Method)

public partial class FieldAssignedWbsPage : ContentPage
{
public FieldAssignedWbsPage(FieldAssignedWbsViewModel viewModel)
{
    InitializeComponent();
    BindingContext = viewModel;
    //The following call does not work 
    //Hover message: Non-invocable member... cannot be called like a method
    await viewModel.GetFieldAssignedWbsListCommand();  
}
}
Todd T
  • 185
  • 2
  • 9

2 Answers2

13

Although the original answer is very valid, I'd recommend installing Microsoft's .NET MAUI Community Toolkit, then using its EventToCommand features.

After installing, add builder.UseMauiCommunityToolkit() to CreateMauiApp() method in MauiProgram.cs.

Then, in relevant XAML page, add this namespace xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" and then you should be able to use this block of code to do what you want:

<ContentPage.Behaviors>
    <toolkit:EventToCommandBehavior
        EventName="Appearing"
        Command="{Binding GetFieldAssignedWbsListCommand}" />
</ContentPage.Behaviors>

I believe that this is a slightly cleaner solution as it avoids populating the code-behind with any code and keeps UI handling purely between the ViewModel and the View.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Jay Ambadkar
  • 193
  • 1
  • 11
  • I appreciate the suggestion and will try this approach. I agree, this will help adhear to the MVVM pattern. Just out of interest, does the .Maui Community, where MVVM seems to be the pattern of choice, cringe when the Blazor Community commonly promote including C# code directly in the pages? – Todd T Aug 12 '22 at 11:20
  • Glad to hear it. Haha, as I'm also new to the Maui community (as well as the whole app community in general), I wouldn't really know but I'm guessing that the answer is yes, for sure. – Jay Ambadkar Aug 13 '22 at 15:30
  • Thanks a ton @JayAmbadkar! In my experience most of the .Maui community would cringe at code on the XAML backing page, @ToddT. Like life though, it really depends on the personality. I fall into the camp of trying my absolute best to put all code on the ViewModel just for consistency. – RAB Dec 21 '22 at 06:28
3

use OnAppearing. You may also need to make the GetFieldAssignedWbsList public

protected override async void OnAppearing()
{
  await viewModel.GetFieldAssignedWbsListCommand.Execute(null);  
}
Jason
  • 86,222
  • 15
  • 131
  • 146
  • 1
    I actually got the following to work public FieldAssignedWbsPage(FieldAssignedWbsViewModel viewModel) { InitializeComponent(); BindingContext = viewModel; viewModel.GetFieldAssignedWbsListCommand.Execute(null); } Thanks! – Todd T Jun 17 '22 at 14:37
  • Mind this caveat, if using shell, though: https://github.com/dotnet/maui/issues/8102 – Heddelin Oct 31 '22 at 11:21