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;
}
}
}