I am trying to write a game in Avalonia 11 with Community Toolkit MVVM.
The game has a MainView which acts as a router, and two child views TitleView and GameView with buttons for navigating between one another. Clicking the buttons sends a message to the MainViewModel to update its Content property. (source: Navigate Views | Avalonia Docs)
The GameView is also somewhat complex - it contains a lot of child elements with SVGs in them. Because of this, the application freezes for a long time when navigating from TitleView to GameView. It's bearable on desktop, but takes a super long time on browser.
I have introduced a loading overlay on top of the MainView's content control with the aim of displaying it while the child view is loading using Task.Run(), but the results are not what I expected.
I have two problems:
- There is still visible stutter during the navigation, and sometimes the UI freezes on the old content even before displaying the loading overlay, which makes the feature useless
- It does not work on browser at all - the contents of
Task.Run()are not executed.
Which makes me wonder if I'm even approaching this from the right angle?
MainView.xaml
<Grid>
<ContentControl Content="{Binding Content}" />
<Border
Background="Black"
IsVisible="{Binding IsLoading}">
<i:Icon
Animation="Pulse"
Value="fa-spinner" />
</Border>
<!-- ... -->
</Grid>
MainViewModel.cs
private ViewModelBase _content = (ViewModelBase)titleViewModel;
private bool _isLoading;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
public ViewModelBase Content
{
get => _content;
set => SetProperty(ref _content, value);
}
// ...
public async void Receive(LeaveGameRequest message)
{
IsLoading = true;
await Task.Run(() =>
{
Content = (ViewModelBase)titleViewModel;
message.Reply(true);
IsLoading = false;
});
}
public async void Receive(StartGameRequest message)
{
IsLoading = true;
await Task.Run(() =>
{
Content = (ViewModelBase)gameViewModel;
message.Reply(true);
IsLoading = false;
});
}
The void Receive(RequestMessage<T>) methods are part of the IRecipient<T> interface, but there doesn't seem to be any problem with the fact that they're async void. The methods are being invoked, it's just the Task.Run() body that is not reachable on browser.