In this example I used async/await to keep the UI responsive so that it is able to update itself at any time.
Otherwise the long running task would have to complete before any update can occur.
Because the long running task was started synchronously on the UI thread before (in your example), the thread was busy executing your method, so no resources have been available to refresh the UI. Executing the method asynchronously executes it on a different thread so that the UI thread is free to execute UI related operations e.g. rendering or updating bindings.
Example
The view:
<Window x:Class="TestRange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestRange"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ViewModel x:Key="ViewModel" />
</Window.Resources>
<StackPanel DataContext="{StaticResource ViewModel}">
<Button Content="Long Running Task" Command="{Binding LongRunningCommand}" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
</Window>
The ViewModel:
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
}
public ICommand LongRunningCommand => new RelayCommand(
async (param) => await this.LongRunningTaskAsync().ConfigureAwait(false), (param) => true);
public async Task LongRunningTaskAsync()
{
await Task.Run(
() =>
{
for (int i = 0; i < 3; i++)
{
Thread.Sleep(5000);
this.Text = $"Iteration #{i + 1} completed";
}
});
}
private string text;
public string Text
{
get { return this.text; }
set
{
this.text = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}