user1522446
user1522446

Reputation: 296

After navigating back button command is not responding to click

I am trying to learn .NET Maui by building a simple app like the android Contacts app. I have a main page that has a list of items with a floating button at the bottom to add a new item as shown in the xaml below. When the user clicks on the imagebutton I navigate to a CreatePage that allows the user to enter the values for each field in an Account object. I am using the CommunityToolkit.MVVM library to handle the MVVM stuff.

In MainPageViewModel I navigate to the CreatePage using the "Shell.Current.GoToAsync(route)" in the CreateNewAccount method shown in the MainPageViewModel:

This works fine for the first time I navigate to add a new Account. When I navigate back to the MainPage and try to click the imagebutton again to add another Account the button is non-responsive. I do not see why it is not handling the button click when I navigated back. Any thoughts?

This is part of the XAML in MainPage.xaml

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <CollectionView Grid.Row="0"
    Background="Transparent"
    IsGrouped="False"
    ItemSizingStrategy="MeasureAllItems"
    ItemsLayout="VerticalList"
    ItemsSource="{Binding Accounts}"
    SelectedItem="{Binding SelectedAccount, Mode=TwoWay}"
    SelectionMode="Single">
        <CollectionView.EmptyView>
            <StackLayout Padding="12">
                <Label HorizontalOptions="Center" Text="No Accounts" />
            </StackLayout>
        </CollectionView.EmptyView>
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="m:Account">
                <StackLayout Orientation="Horizontal" Padding="10">
                    <Label Text="{Binding AccountName}" 
                        FontSize="Large"/>
                </StackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

    <ImageButton
    Grid.Row="0"
    Command="{Binding CreateCommand}"
    Source="add_box_black_48dp.svg"
    Background="Transparent" 
    HorizontalOptions="End"
    VerticalOptions="End"/>
</Grid>
public class MainPageViewModel : ObservableObject
{
    private IDataContext _context;
    private bool _isBusy;
    private Account _selectedAccount;

    public ObservableCollection<Account> Accounts { get; private set; }
    public AsyncRelayCommand RefreshCommand { get; private set; }
    public AsyncRelayCommand CreateCommand { get; private set; }

    public bool IsBusy { get=>_isBusy; set => SetProperty(ref _isBusy, value); } 
    public Account SelectedAccount { get=>_selectedAccount;  set => SetProperty(ref _selectedAccount, value); }

    public MainPageViewModel(IDataContext context)
    {
        _context = context;
        Accounts = new ObservableCollection<Account>();
        RefreshCommand = new AsyncRelayCommand(Refresh);
        CreateCommand = new AsyncRelayCommand(CreateNewAccount);

        Accounts.Add(new Account { Id = 1, AccountName = "a1", UserName = "a2", Password = "a3" });
    }

    async Task CreateNewAccount()
    {
        var route = $"{nameof(CreatePage)}";
        await Shell.Current.GoToAsync(route);
    }

    internal async Task InitializeAsync()
    {
        await Refresh();
    }

    async Task Refresh()
    {
        IsBusy = true;

        var accounts = await _context.GetAllAsync();

        if (Accounts.Count > 0)
        {
            Accounts.Clear();
        }
        foreach (var item in accounts)
        {
            Accounts.Add(item);
        }
        IsBusy = false;
    }

}

In CreatePageViewModel I create an AsyncRelayCommand as follows and navigate back to the mainpage after the Account is added using "Shell.Current.GoToAsync("..")"

public AsyncRelayCommand SaveCommand { get; private set; }
public CreatePageViewModel(IDataContext dataContext)
{
    _dataContext = dataContext;
    NewAccount = new Account();
    SaveCommand = new AsyncRelayCommand(AddAccount);
}

private async Task AddAccount()
{
    var accountFound = await _dataContext.FindByName(NewAccount.AccountName);
    if (accountFound is not null)
    {
        await Application.Current.MainPage.DisplayAlert("Alert", "Account alreaady exists", "OK");
        return;
    }

    await _dataContext.InsertAccountAsync(NewAccount);
    await Shell.Current.GoToAsync("..");
}

Upvotes: 1

Views: 2733

Answers (1)

mdimai666
mdimai666

Reputation: 787

why you await all events?

async Task CreateNewAccount()
{
    var route = $"{nameof(CreatePage)}";
    // we won't wait - await Shell.Current.GoToAsync(route);
    _ = Shell.Current.GoToAsync(route);
}

and everything will work

Upvotes: 0

Related Questions