系统相关
首页 > 系统相关> > 绑定到运行长进程的依赖对象的WPF ProgressBar更新

绑定到运行长进程的依赖对象的WPF ProgressBar更新

作者:互联网

我想将WPF ProgressBar的value属性绑定到在长时间运行的过程中更新的依赖项属性.如果从主线程调用了长时间运行的进程,则这将阻止UI(并因此禁止进度条)更新,直到该进程完成为止-从而阻止了显示该进程所需的进度.长时间运行的进程也无法通过旋转单独的线程来运行,因为无法将依赖项属性从其他线程更新为其所有者(即创建它的线程).

在下面的代码中,单击按钮后,长时间运行的进程将运行,并且进度条从完成时的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);
        }
    }
}

附言我知道有一种方法可以通过将ProgressBar实例作为参数传递给长时间运行的进程来实现,以便它可以直接通过Dispatcher.Invoke更新它,但这不是我想要的.我想通过绑定到依赖项属性来更新进度条.

谢谢

肖恩

解决方法:

我会尝试比欣快更好.

您需要使用BackgroundWorker运行LongRunningProcess,该进程在另一个线程上运行该进程,然后使用ProgressChanged事件更新该属性.

// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
    MyFoo.ProgressValue = e.ProgressPercentage;
}

标签:multithreading,binding,wpf-controls,wpf,c
来源: https://codeday.me/bug/20191023/1915359.html