WPF를 통해서 Uri를 통해 파일을 다운로드하면서, 실시간으로 다운로드 상태를 StatusFileSize
에 보여주려고 합니다. 나중에 statusbar
을 추가해서 실시간으로 변화하는 수치를 보여주려고 합니다.
문제점 및 개선 방향
-
당장 문제가 발생한 부분은 WindowsVM의
DownloadFile
함수에서StatusFileSize= (int)(dProgressPercentage * 100);
를 OnPropertyChanged로 설정했음에도, View에서StatusFileSize
가 실시간으로 변경되지 않고 완료된 다음에서야100
으로 됩니다. -
또한 현재는 WindowsVM에 다운로드로직(
DownloadFile
함수)이 들어가 있는데 이를 별도 폴더(Helpers)를 생성해서 분리한 뒤, WindowsVM에서 호출해서 사용하려고 합니다. 그럴 경우,StatusFileSize
에 대한 바인딩이 기존View<-- WindowsVM
에서,View<--WindowsVM<--Helper
로 진행되기 때문에 Helper에서 변경되는StatusFileSize
를 어떻게 View까지 가져올지 고민됩니다.
관련해서 조언을 부탁드립니다.
<Window x:Class="WPF_DownloadFile.View.Driver_Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_DownloadFile.View"
xmlns:vm="clr-namespace:WPF_DownloadFile.ViewModels"
mc:Ignorable="d"
Title="Driver_Page1"
Height="450"
Width="800">
<Window.Resources>
<vm:WindowsVM x:Key="vm" />
</Window.Resources>
<DockPanel>
<StackPanel DockPanel.Dock="Top"
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="10"
DataContext="{StaticResource vm}">
<Button Content="Download"
Margin="10"
Command="{Binding folderCommand}" />
<TextBlock Text="{Binding FolderPath}"
FontSize="15" />
<TextBlock Text="{Binding StatusFileSize, IsAsync=True}"
FontSize="15" />
</StackPanel>
</DockPanel>
</Window>
namespace WPF_DownloadFile.ViewModels
{
public class WindowsVM: INotifyPropertyChanged
{
public FolderCommand folderCommand { get; set; }
private string folderPath;
public string FolderPath
{
get { return folderPath; }
set
{
folderPath = value;
OnPropertyChanged("FolderPath");
}
}
private int _statusFileSize;
public int StatusFileSize
{
get { return _statusFileSize; }
set { _statusFileSize = value; OnPropertyChanged("StatusFileSize"); }
}
public WindowsVM()
{
folderCommand = new FolderCommand(this);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void GetFolderPath()
{
string path = FolderHelper.GetFolderDirectory();
FolderPath = path;
foreach (var sw in SelectedSoftwares)
{
DownloadFile(sw, path);
}
}
public void DownloadFile(File file, string path)
{
string orignalFilePath = file.OriginUri;
string destinationFilePath = Path.Combine(path, file.FileName);
Uri url = new Uri(orignalFilePath);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
Int64 iSize = response.ContentLength;
Int64 iRunningByteTotal = 0;
using (System.Net.WebClient client = new System.Net.WebClient())
{
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(orignalFilePath)))
{
using (Stream streamLocal = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
StatusFileSize= (int)(dProgressPercentage * 100);
Console.WriteLine(iProgressPercentage);
}
streamLocal.Close();
}
streamRemote.Close();
}
}
}
}
}
namespace WPF_DownloadFile.ViewModels.Commands
{
public class FolderCommand : ICommand
{
WindowsVM vm;
public FolderCommand(WindowsVM _vm)
{
vm= _vm;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
vm.GetFolderPath();
}
}
}
감사합니다.