1

我有一个进度条,它的值绑定到一个属性:

                <ProgressBar x:Name="progressBar"
                         Margin="0,2,0,0"
                         Height="20"
                         Value="{Binding CompassLogLoadPercent}"
                         Foreground="Blue"
                         Visibility="{Binding CompassLogLoadCompleted, 
                Converter={StaticResource BooleanToVisibilityConverter}}"
                         ToolTip="Loading">
            </ProgressBar>

和财产:

       public double CompassLogLoadPercent {
        get { return _compassLogLoadPercent; }
        private set {
            if (value != _compassLogLoadPercent) {
                _compassLogLoadPercent = value;
                NotifyPropertyChanged();
            }
        }
    }

并在单独的线程中更新其值:

   for (int j = 0; j < lines.Count(); j++) {
      ...
      CompassLogLoadPercent = ((double) j /lines.Count())*100;
   }

并且线程是使用 TASK 创建的:

Task.Run(() => { LoadLogFile(fileName); });

为什么进度条没有更新,我应该如何解决这个问题?

更新更多信息

数据上下文:(我确定数据上下文是正确的)

cLT.progressBar.DataContext = logSession;

和实施INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(
        [CallerMemberName] String propertyName = "") {
        PropertyChangedEventHandler eventHandler = PropertyChanged;

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
4

1 回答 1

4

问题在于你没有向我们展示的东西。基本技术是声音。(特别是,在工作线程上引发事件通知并没有错PropertyChanged,因为 WPF 的数据绑定系统会检测到何时发生这种情况,并自动安排更新 UI 线程上的目标 UI 元素。)

这是一个有效的完整示例。这是您的 XAML:

<Window x:Class="BackgroundThreadUpdate.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">
    <Grid>
        <ProgressBar
            x:Name="progressBar"
            VerticalAlignment="Top" Height="20"
            Value="{Binding CompassLogLoadPercent}">
        </ProgressBar>
        <Button Content="Button" HorizontalAlignment="Left" Margin="10,25,0,0" VerticalAlignment="Top"
                Width="75" RenderTransformOrigin="-1.24,-0.045" Click="Button_Click_1"/>

    </Grid>
</Window>

这是您的代码隐藏:

using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace BackgroundThreadUpdate
{
    public partial class MainWindow : Window
    {
        private MySource _src;
        public MainWindow()
        {
            InitializeComponent();
            _src = new MySource();
            DataContext = _src;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Task.Run(() =>
            {
                for (int i = 0; i < 100; ++i)
                {
                    Thread.Sleep(100);
                    _src.CompassLogLoadPercent = i;
                }
            });
        }
    }

    public class MySource : INotifyPropertyChanged
    {
        private double _compassLogLoadPercent;
        public double CompassLogLoadPercent
        {
            get
            {
                return _compassLogLoadPercent;
            }
            set
            {
                if (_compassLogLoadPercent != value)
                {
                    _compassLogLoadPercent = value;
                    OnPropertyChanged("CompassLogLoadPercent");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

这说明了您尝试使用的技术的工作版本。

所以你的不工作的事实一定是由于你没有向我们展示的东西。一些可能的解释:

  • 您的 UI 线程可能被阻止。如果 UI 线程很忙,则不会处理数据绑定更新。(当数据绑定在工作线程上检测到来自数据源的更改时,它会向相关的调度程序线程发送一条消息,如果调度程序线程很忙,则不会处理该消息。)
  • 数据源可能不DataContext适合您ProgressBar- 您没有向我们展示您设置上下文的位置,因此这很可能是错误的。
  • 引发PropertyChanged事件的代码(您的NotifyPropertyChanged代码)可能是错误的 - 您没有显示该代码,并且不清楚它如何知道在引发事件时使用什么属性名称。

要检查第一个,只需查看在此后台工作进行时您的 UI 是否响应用户输入。如果不是,那么这就是更新没有通过的原因。

2 月 25 日更新以添加相关链接

在考虑关于如何处理这种情况我还能说些什么时,我得出的结论是它太大而无法放入单个 StackOverflow 答案中。所以我写了一系列关于在需要将信息加载到 UI 的后台线程上进行非平凡处理时的性能注意事项的博客文章:http: //www.interact-sw.co.uk/iangblog/2013/02/ 14/wpf-异步太快

于 2013-02-11T10:52:21.667 回答