Q:

UWP Boolean not being updated in UI if set after awaited async call

I have a public boolean in my UWP app used to show/hide a ProgressBar. I've used the same pattern elsewhere and it seems to work okay, but I'm having an issue on a specific page where it doesn't seem to update in the UI only if I set the boolean after an awaited async call (same pattern as the working page).
Here is my XAML View:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <TextBlock Text="{ x:Bind Vm.IsLoaded }" Margin="112,272,-112,-272"></TextBlock>
</Grid>

And the codebehind:
public sealed partial class MainPage : Page
{
    public MainPageViewModel Vm => DataContext as MainPageViewModel;
    public MainPage()
    {
        this.InitializeComponent();
        this.DataContext = new MainPageViewModel();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        Vm.GetProjectData();
    }
}

Here is my MainPageViewModel.cs
public class MainPageViewModel : ViewModel
{
    public ObservableCollection<Project> Projects { get; set; } = new ObservableCollection<Project>();

    private bool _isLoaded;
    public bool IsLoaded
    {
        get { return _isLoaded; }
        set
        {
            _isLoaded = value;
            OnPropertyChanged();
        }
    }

    public async Task GetProjectData()
    {
        // If I put `IsLoaded = true;` here it displays `true` in the UI
        var projectsResponse = await HttpUtil.GetAsync(StringUtil.ProjectsUrl());
        // If I put `IsLoaded = true;` here it still displays `false` in the UI
        if (projectsResponse.IsSuccessStatusCode)
        {
            var projectsResponseString = await projectsResponse.Content.ReadAsStringAsync();
            var projects = JsonUtil.SerializeJsonToObject<List<Project>>(projectsResponseString);

            foreach (var project in projects)
            {
                Projects.Add(project);
            }

            IsLoaded = true;
       }
    }
}

And my ViewModel.cs
public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

No matter where I put the IsLoaded = true; it always hits OnPropertyChanged(). 
Here is my working code:
ProjectViewViewModel.cs:
public class ProjectViewViewModel : ViewModel
{
    public ObservableCollection<Story> MyData { get; set; } = new ObservableCollection<Story>();
    private bool _dataIsLoaded;
    public bool DataIsLoaded
    {
        get { return _dataIsLoaded; }
        set
        {
            _dataIsLoaded = value;
            OnPropertyChanged();
        }
    }

    public async Task GetData(Project project)
    {
        DataIsLoaded = false;
        var stringResponse = await HttpUtil.GetAsync(StringUtil.Query(project.Id, "MB"));
        if (stringResponse.IsSuccessStatusCode)
        {
            // Do Stuff

            DataIsLoaded = true;
        }
    }
}

ProjectView.xaml.cs
public sealed partial class ProjectView : Page
{
    public Project Project { get; set; }
    public bool IsLoaded { get; set; }
    public ProjectViewViewModel Vm => DataContext as ProjectViewViewModel;
    public ProjectView()
    {
        this.InitializeComponent();
        this.DataContext = new ProjectViewViewModel();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        Project = e.Parameter as Project;
        Vm.GetData(Project);
    }
}

I feel like I'm missing something extremely obvious but I can't see the wood through the trees and it's driving me nuts. Any help is greatly appreciated!

A:

I believe the problem you are having is in your mark up.  x:Bind has a default binding mode of OneTime; so the text in your text block is bound to the value of IsLoaded at application start up, or when the data context for the text block changed.  
Setting the binding mode to OneWay should result in the value in the text block updating after the async function has returned.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <TextBlock Text="{ x:Bind Path=Vm.IsLoaded, Mode=OneWay }" Margin="112,272,-112,-272"></TextBlock>
</Grid>

If you're interested, this article goes into detail on the use of x:Bind.  Also, this article covers the values in the BindingMode enumeration.

