Reputation: 296
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
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