单击按钮,在WPF进度条中报告以下方法的进度?

时间:2012-10-01 19:04:58

标签: c# wpf

我有以下按钮点击执行的方法:

 private void CopyDirectoriesAndFiles(string source, string target, string[] excludedFolders)
        {

            foreach (string dir in Directory.GetDirectories(source, "*", System.IO.SearchOption.AllDirectories))
                if (!excludedFolders.Contains(dir))
                    Directory.CreateDirectory(target + dir.Substring(source.Length));

            foreach (string file_name in Directory.GetFiles(source, "*.*", System.IO.SearchOption.AllDirectories))
                if (!File.Exists(Path.Combine(target + file_name.Substring(source.Length))))
                    File.Copy(file_name, target + file_name.Substring(source.Length));

        }

按钮单击还有其他一些方法,但它们运行时间不会很长,但即使这样,我如何显示和更新每个运行的进度条。我放了一个文本框,但只有在完成所有内容后才会写入文本框。我的按钮顺序可能如下所示:

InitializeStuff();

CopyFiles();

CleanUp();

进度条不是绝对必要的,虽然很好。如果我可以在每次方法完成而不是在最后完成时更新文本框,那就太棒了。

2 个答案:

答案 0 :(得分:5)

这是使用MVVM的完整工作模型:

观点:

<Window x:Class="CopyFiles.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"
        xmlns:model="clr-namespace:CopyFiles">

    <Window.DataContext>
        <model:CopyModel />
    </Window.DataContext>

    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
    </Window.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>


        <Label Grid.Row="0" Grid.Column="0" Name="sourceLabel">Source</Label>
        <TextBox Text="{Binding Source, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1" Name="sourceTextBox" Margin="5"/>

        <Label Grid.Row="1" Grid.Column="0"  Name="destinationLabel">Destination</Label>
        <TextBox Text="{Binding Destination, Mode =TwoWay, UpdateSourceTrigger=PropertyChanged}"  Grid.Row="1" Grid.Column="1" Name="destinationTextBox" Margin="5" />

        <Button Command="{Binding CopyCommand}" Grid.Row="2" Grid.ColumnSpan="2" Content="Copy" Name="copyButton" Width="40" HorizontalAlignment="Center"  Margin="5"/>

        <ProgressBar Visibility="{Binding CopyInProgress, Converter={StaticResource booleanToVisibilityConverter}}" Value="{Binding Progress}" Grid.Row="3" Grid.ColumnSpan="2"  Height="20" Name="copyProgressBar" Margin="5" />
    </Grid>
</Window>

ViewModel:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using Microsoft.Practices.Prism.Commands;

namespace CopyFiles
{
    public class CopyModel: INotifyPropertyChanged
    {

        private string source;
        private string destination;
        private bool copyInProgress;
        private int progress;
        private ObservableCollection<string> excludedDirectories;

        public CopyModel()
        {
            this.CopyCommand = new DelegateCommand(ExecuteCopy, CanCopy);
            this.excludedDirectories = new ObservableCollection<string>();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public string Source
        {
            get { return source; }
            set
            {
                source = value;
                RaisePropertyChanged("Source");
                CopyCommand.RaiseCanExecuteChanged();
            }
        }

        public string Destination
        {
            get { return destination; }
            set
            {
                destination = value;
                RaisePropertyChanged("Destination");
                CopyCommand.RaiseCanExecuteChanged();
            }
        }

        public bool CopyInProgress
        {
            get { return copyInProgress; }
            set
            {
                copyInProgress = value;
                RaisePropertyChanged("CopyInProgress");
                CopyCommand.RaiseCanExecuteChanged();
            }
        }

        public int Progress
        {
            get { return progress; }
            set
            {
                progress = value;
                RaisePropertyChanged("Progress");
            }
        }

        public ObservableCollection<string> ExcludedDirectories
        {
            get { return excludedDirectories; }
            set 
            { 
                excludedDirectories = value;
                RaisePropertyChanged("ExcludedDirectories");
            }
        }


        public DelegateCommand CopyCommand { get; set; }

        public bool CanCopy()
        {
            return (!string.IsNullOrEmpty(Source) &&
                    !string.IsNullOrEmpty(Destination) &&
                    !CopyInProgress);
        }

        public void ExecuteCopy()
        {
            BackgroundWorker copyWorker = new BackgroundWorker();
            copyWorker.DoWork +=new DoWorkEventHandler(copyWorker_DoWork);
            copyWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(copyWorker_RunWorkerCompleted);
            copyWorker.ProgressChanged += new ProgressChangedEventHandler(copyWorker_ProgressChanged);
            copyWorker.WorkerReportsProgress = true;
            copyWorker.RunWorkerAsync();
        }

        private void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if(handler != null) 
            {
                var eventArgs = new PropertyChangedEventArgs(propertyName);
                handler(this, eventArgs);
            }
        }

        private void copyWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var worker = sender as BackgroundWorker;
            this.CopyInProgress = true;
            worker.ReportProgress(0);

            var directories = Directory.GetDirectories(source, "*", System.IO.SearchOption.AllDirectories);
            var files = Directory.GetFiles(source, "*.*", System.IO.SearchOption.AllDirectories);
            var total = directories.Length + files.Length;
            int complete = 0;

            foreach (string dir in directories)
            {
                if (!ExcludedDirectories.Contains(dir))
                    Directory.CreateDirectory(destination + dir.Substring(source.Length));
                complete++;
                worker.ReportProgress(CalculateProgress(total, complete));
            }

            foreach (string file_name in files)
            {
                if (!File.Exists(Path.Combine(destination + file_name.Substring(source.Length))))
                    File.Copy(file_name, destination + file_name.Substring(source.Length));
                complete++;
                worker.ReportProgress(CalculateProgress(total, complete));
            }
        }

        private static int CalculateProgress(int total, int complete)
        {
            // avoid divide by zero error
            if (total == 0) return 0;
            // calculate percentage complete
            var result = (double)complete / (double)total;
            var percentage = result * 100.0;
            // make sure result is within bounds and return as integer;
            return Math.Max(0,Math.Min(100,(int)percentage));
        }

        private void copyWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.Progress = e.ProgressPercentage;
        }

        private void copyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.CopyInProgress = false;
        }
    }
}

答案 1 :(得分:2)

  

我有以下按钮点击执行的方法:

不应该。这会将您的用户界面冻结太长时间。

使用背景工作者。 [1][2][3]