Я хочу связать свойство value WPF ProgressBar со свойством зависимостей, которое обновляется во время длительного процесса. Если длительный процесс вызывается из основного потока, это блокирует обновление пользовательского интерфейса (и, следовательно, ProgressBar) до тех пор, пока процесс не завершится, что предотвращает желаемый прогресс в отображаемом процессе. Длительный процесс также не может быть запущен путем вращения отдельного потока, потому что невозможно обновить свойство зависимости из другого потока для его владельца (то есть потока, в котором он был создан).
В приведенном ниже коде при нажатии кнопки запускается длительный процесс, а индикатор выполнения скачет с 0% до 100% по завершении. Вместо этого я хочу иметь возможность щелкать по кнопке, чтобы индикатор выполнения отображал прогресс в течение длительного процесса (т. Е. Не только обновление с 0% до 100% после завершения процесса, но и плавное продвижение).
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
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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(); // Since this runs on same thread as UI, progress bar does not update until the long running process completes.
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);
}
}
}
P.S. Я знаю, что есть способ сделать это, передав экземпляр ProgressBar в качестве аргумента длительному процессу, чтобы он мог обновить его напрямую через Dispatcher.Invoke, но это не то, что я хочу. Я хочу, чтобы индикатор выполнения обновлялся через привязку к свойству зависимости.
Спасибо
Sean