I want to bind the value property of WPF ProgressBar to a dependency property that has been updated over a long process. If a lengthy process is called from the main thread, this blocks the change in the user interface (and therefore the ProgressBar) until the process terminates - preventing the desired progress through the displayed process. A lengthy process also cannot be started by rotating a separate thread, because it is impossible to update the dependency property of another thread to its owner (i.e., the thread on which it was created).
In the code below, when the button is pressed, a lengthy process is performed and the progress bar goes from 0% to 100% when it is completed. Instead, I want you to be able to click on the button, and the progress bar will show the progress of the long course (i.e. not only updating from 0% to 100% when the process is complete, but will show a smooth progress).
MainWindow.xaml
<Window x:Class="ProgressBarTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel>
<Button Width="200" Height="50" x:Name="btnRun" Click="btnRun_Click">Run Process</Button>
<ProgressBar Width="200" Height="20" x:Name="pbProgress" Minimum="0" Maximum="100" Value="{Binding Path=MyFoo.ProgressValue}"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Threading;
namespace ProgressBarTest
{
public partial class MainWindow : Window
{
public Foo MyFoo { get; set; }
public MainWindow()
{
MyFoo = new Foo();
InitializeComponent();
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
btnRun.IsEnabled = false;
MyFoo.LongRunningProcess();
btnRun.IsEnabled = true;
}
}
public class Foo : DependencyObject
{
public static readonly DependencyProperty ProgressValueProperty = DependencyProperty.Register("ProgressValue", typeof(double), typeof(Foo));
public double ProgressValue
{
get { return (double)GetValue(ProgressValueProperty); }
set
{
SetValue(ProgressValueProperty, value);
}
}
public Foo()
{
ProgressValue = 0;
}
public void LongRunningProcess()
{
do
{
ProgressValue += 1;
Thread.Sleep(30);
}
while (ProgressValue < 100);
}
}
}
PS I know that I can do this by passing an instance of ProgressBar as an argument for a long process so that it can update it directly through Dispatcher.Invoke, but that is not what I want. I want to update the progress bar with a dependency property.
thank
Sean
source
share