进度条未更新

时间:2017-12-13 17:13:34

标签: c# wpf mvvm binding progress-bar

我在{Binding CurrentProgress}Progressbar Listview控制值出现问题。在我的代码中,我能够添加一些具有CurrentProgress属性的属性的项目。项目正在以适当的方式添加,但只有一个进度条更新。这是代码:

MODEL:

sealed public class Mp3Model : INotifyPropertyChanged
{
    public string Name { get; set; }

    private double _currentProgress;
    public double CurrentProgress
    {
        get
        {
            return _currentProgress;
        }
        set
        {
            _currentProgress = value;
            OnPropertyChanged("CurrentProgress");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

XAML:

<ListView ItemsSource="{Binding Mp3List}">
    <ListView.View>
        <GridView>
            <GridViewColumn
                Width="140"
                DisplayMemberBinding="{Binding Name}"
                Header="Track Name" />
            <GridViewColumn Width="300" Header="Progress">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <Grid Width="320">
                            <ProgressBar
                                Height="40"
                                Margin="10"
                                IsIndeterminate="{Binding IsIndeterminate}"
                                Maximum="100"
                                Minimum="0"
                                Visibility="{Binding IsProgressDownloadVisible}"
                                Value="{Binding CurrentProgress}" />
                            <TextBlock
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Text="{Binding CurrentProgress, StringFormat={}{0:0}%}"
                                Visibility="{Binding IsPercentLabelVisible}" />
                            <TextBlock
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Text="{Binding ConvertingLabelText}"
                                Visibility="{Binding IsConvertingLabelVisible}" />
                            <TextBlock
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Text="{Binding IsOperationDone}"
                                Visibility="{Binding IsOperationDoneLabelVisible}" />
                        </Grid>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

视图模型(方法)

private void SaveVideoToDisk()
{
    Task.Factory.StartNew(() =>
    {
        long currentLocalProgress = 0;
        this._fileHelper = new FileHelper();
        this._model = new Mp3Model();

        using (var service = Client.For(YouTube.Default))
        {
            using (var video = service.GetVideo(YoutubeLinkUrl))
            {
                _fileHelper.DefaultTrackName = video.FullName;
                _fileHelper.DefaultTrackPath = _fileHelper.Path + "\\" + _fileHelper.DefaultTrackName;
                _fileHelper.DefaultTrackHiddenPath = _fileHelper.HiddenPath + "\\" + _fileHelper.DefaultTrackName;
                _fileHelper.TmpTrackPath = _fileHelper.PreparePathForFFmpeg(_fileHelper.DefaultTrackHiddenPath);

                _model = new Mp3Model()
                {
                    Name = _fileHelper.DefaultTrackName,
                    IsProgressDownloadVisible = Visibility.Visible,
                    IsPercentLabelVisible = Visibility.Visible,
                    IsConvertingLabelVisible = Visibility.Hidden,
                    IsOperationDoneLabelVisible = Visibility.Hidden,
                    ConvertingLabelText = Consts.ConvertingPleaseWait,
                    CurrentProgress = 0,
                };

                Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this._mp3List.Add(_model);
                }));

                using (var outFile = File.OpenWrite(_fileHelper.TmpTrackPath))
                {
                    using (var progressStream = new ProgressStream(outFile))
                    {
                        var streamLength = (long)video.StreamLength();

                        progressStream.BytesMoved += (sender, args) =>
                        {
                            currentLocalProgress = args.StreamLength * 100 / streamLength;
                            _model.CurrentProgress = currentLocalProgress;
                            Debug.WriteLine($"{_model.CurrentProgress}% of video downloaded");
                        };

                        video.Stream().CopyTo(progressStream);
                    }
                }
                //ExtractAudioFromVideo(_fileHelper.TmpTrackPath);
            }
        }
    });
}

ProgressBar Binded值的位置:

progressStream.BytesMoved += (sender, args) =>
{
    currentLocalProgress = args.StreamLength * 100 / streamLength;
    _model.CurrentProgress = currentLocalProgress;
    Debug.WriteLine($"{_model.CurrentProgress}% of video downloaded");
};

有没有人有任何想法?

2 个答案:

答案 0 :(得分:3)

尝试猜测:您更新_model字段,每次调用save video to disk方法时都会覆盖该字段。这可能只有在课程实例中只能调用一种方法时才有效(但由于我们没有clas,我们不知道它是列表还是视频)。

所以我想说调用两次方法会阻止第一个_model实例被更新(因为lambda捕获了持有对象的变量)

答案 1 :(得分:0)

xaml给我看起来很好,但我遇到了类似的问题,我修复如下:

Mode=OneWay添加到Value="{Binding CurrentProgress, Mode=OneWay}"

每当您更新CurrentProgress时,请使用Dispatcher:Application.Current.Dispatcher.Invoke(() => CurrentProgress++);

我希望它可以帮助您找到解决方案。

编辑:只是一个建议,我使用以下OnPropertyChanged,因此您不必每次都写出属性的名称= D.

protected void OnPropertyChange([CallerMemberName] string inPropertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(inPropertyName));