0

ボタンクリックで実行される次のメソッドがあります。

 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();

プログレスバーは、いいのですが、絶対に必要というわけではありません。メソッドが最後ではなく、完了するたびにテキストボックスを更新できると便利です。

4

2 に答える 2

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>

ビューモデル:

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;
        }
    }
}
于 2012-10-01T21:43:08.207 に答える
2

ボタンクリックで実行される次のメソッドがあります。

そうであってはなりません。これにより、UI が長時間フリーズします。

バックグラウンドワーカーを使用します。[1][2]および[3]

于 2012-10-01T19:10:36.003 に答える