Skip to content

Instantly share code, notes, and snippets.

@fearofcode
Created September 4, 2018 08:52
Show Gist options
  • Save fearofcode/31413beec354b4e1f74d947e069c7f21 to your computer and use it in GitHub Desktop.
Save fearofcode/31413beec354b4e1f74d947e069c7f21 to your computer and use it in GitHub Desktop.
simple .NET WPF BackgroundWorker test where long running task reports text back and it scrolls into a textbox that won't get messed up when you click/select it. the textbox scrolls to the end as lines come in.
<Window x:Class="databinding.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:databinding"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="400">
<Grid>
<StackPanel Orientation="Vertical"
Margin="10">
<Button Name="BackgroundWorkerButton"
Height="25"
Content="Do Async"
Margin="0 5 0 5"
Click="BackgroundWorkerButton_Click" />
<Button Name="BackgroundWorkerButtonCancel"
Height="25"
Content="Cancel"
Margin="0 5 0 5"
Click="BackgroundWorkerButtonCancel_Click" />
<TextBox Height="100"
IsReadOnly="True"
TextWrapping="Wrap"
AcceptsReturn="True"
SelectionChanged="progressBox_SelectionChanged"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Text="Output will go here"
Name="progressBox"
/>
<ProgressBar Name="BackgroundWorkerProgressBar"
Height="25"
Maximum="1000"
Margin="0 5 0 5" />
<Button Name="UIResponsiveButton"
Height="25"
Content="UI Still Works"
Margin="0 5 0 5"
Click="UIResponsiveButton_Click" />
</StackPanel>
</Grid>
</Window>
using System.ComponentModel;
using System.Text;
using System.Threading;
using System.Windows;
namespace databinding
{
public partial class MainWindow : Window
{
private double progressBarMaximum;
private StringBuilder stringBuilder;
private BackgroundWorker backgroundWorker = new BackgroundWorker()
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
public MainWindow()
{
InitializeComponent();
stringBuilder = new StringBuilder(1000);
backgroundWorker.DoWork += (s, args) =>
{
backgroundWorker.ReportProgress(0);
for (int i = 1; i <= progressBarMaximum; i++)
{
Thread.Sleep(50);
backgroundWorker.ReportProgress(i, $"Computed {i}");
if (backgroundWorker.CancellationPending)
{
backgroundWorker.ReportProgress(0);
break;
}
}
};
backgroundWorker.ProgressChanged += (s, args) =>
{
stringBuilder.AppendLine((string)args.UserState);
progressBox.Text = stringBuilder.ToString();
progressBox.ScrollToEnd();
BackgroundWorkerProgressBar.Value = args.ProgressPercentage;
};
backgroundWorker.RunWorkerCompleted += (s, args) =>
{
BackgroundWorkerButton.IsEnabled = true;
BackgroundWorkerButtonCancel.IsEnabled = false;
stringBuilder = new StringBuilder(1000);
};
BackgroundWorkerButtonCancel.IsEnabled = false;
}
private void BackgroundWorkerButton_Click(object sender, RoutedEventArgs e)
{
BackgroundWorkerButton.IsEnabled = false;
BackgroundWorkerButtonCancel.IsEnabled = true;
progressBox.Text = "";
progressBarMaximum = BackgroundWorkerProgressBar.Maximum;
backgroundWorker.RunWorkerAsync();
}
private void UIResponsiveButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("UI still works");
}
private void BackgroundWorkerButtonCancel_Click(object sender, RoutedEventArgs e)
{
backgroundWorker.CancelAsync();
BackgroundWorkerButton.IsEnabled = true;
}
private void progressBox_SelectionChanged(object sender, RoutedEventArgs e)
{
progressBox.ScrollToEnd();
e.Handled = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment