【发布时间】:2019-09-12 07:47:41
【问题描述】:
我正在尝试构建一个 WPF 应用程序,它使用 SSH.NET 在服务器上并行上传多个文件并为每个文件显示一个进度条。
在视图中,我有以下数据网格:
<DataGrid
AlternatingRowBackground="LightGray"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
ItemsSource="{Binding Files, Mode=TwoWay}"
SelectedItem="{Binding SelectedFile, Mode=OneWayToSource}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=DisplayName}" Header="File" />
<DataGridTextColumn Binding="{Binding Path=FileSize}" Header="Size" />
<DataGridTextColumn Binding="{Binding Path=IsUploaded, Mode=OneWay}" Header="Uploaded" />
<DataGridTextColumn Binding="{Binding Path=IsUploading, Mode=OneWay}" Header="Uploading" />
<DataGridTemplateColumn Header="Progress">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<ProgressBar
Width="300"
Height="10"
Maximum="{Binding FileSize}"
Value="{Binding Path=SizeUploaded, Mode=OneWay}" />
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
Text="{Binding Path=PercentageCompleted, StringFormat={}{0}%}" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Start">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="UploadFile" Content="Start" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Stop">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="StopTransfer" Content="Stop" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Remove">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="RemoveFile" Content="Remove" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
ViewModel 具有绑定 DataGrid 的项和 SelectedItem 的公共属性:
public BindingList<UploadedFile> Files { get; set; }
public UploadedFile SelectedFile
{
get { return _selectedFile; }
set
{
_selectedFile = value;
NotifyOfPropertyChange(() => SelectedFile);
}
}
要从硬盘驱动器获取文件,我正在使用 MvvmDialgos 库并调用此方法来创建一个新的 UploadedFile 并将其添加到 Files 列表中:
public void SelectFile()
{
var success = OpenFileDialog(this);
if (success)
{
var file = new UploadedFile
{
FullName = OpenFileDialogSettings.FileName
};
file.DisplayName = Path.GetFileName(file.FullName);
var fileInfo = new FileInfo(file.FullName);
file.FileSize = (int)fileInfo.Length;
if (Files == null)
Files = new BindingList<UploadedFile>();
Files.Add(file);
NotifyOfPropertyChange(() => Files);
}
}
要使用 SSH.NET 在服务器上上传文件,我正在执行以下操作:
private async Task UploadFileToServer(ConnectionModel connection, string fileName, string destinationPath)
{
if (!string.IsNullOrWhiteSpace(destinationPath))
{
await Task.Run(() =>
{
var currentUploadedFile = Files.FirstOrDefault(x => x.FullName == fileName);
currentUploadedFile.IsUploading = true;
try
{
_fileManager.UploadFile(connection, fileName, destinationPath);
currentUploadedFile.IsUploaded = true;
}
catch (Exception ex)
{
BroadCastErrorMessage(ex.Message);
IsConnectionTabExpanded = true;
}
finally
{
currentUploadedFile.IsUploading = false;
}
});
}
else
{
BroadCastErrorMessage("ERROR: You must enter a destination folder!");
IsConnectionTabExpanded = true;
}
}
FileManager 调用实际上是 ssh.net 库:
using (var fs = new FileStream(fileName, FileMode.Open))
{
fullFileName = fileName;
sftp.BufferSize = 4 * 1024;
sftp.UploadFile(fs, Path.GetFileName(fileName), true, uploadCallback: UpdateProgresBar);
OnFileUploadedSuccess($@"Successfully uploaded {fileName} in {path}.");
status = FileRenamedStatus.Uploaded;
}
并使用上传的大小引发事件:
private void UpdateProgresBar(ulong uploaded)
{
OnFileUploading(uploaded);
}
protected void OnFileUploading(ulong uploaded)
{
FileUploading?.Invoke(this, new UploadingEventArgs(new UploadedFile
{
SizeUploaded = (int)uploaded,
FullName = fullFileName
}));
}
在 ViewModel 中,我正在监听事件并更新进度条:
private void OnUploading(object sender, UploadingEventArgs e)
{
foreach (var item in Files.ToList())
{
if (item.FullName == e.UploadedFile.FullName)
{
item.SizeUploaded = e.UploadedFile.SizeUploaded;
var percentage = (double)e.UploadedFile.SizeUploaded / item.FileSize;
item.PercentageCompleted = Math.Round(percentage * 100, 2);
}
}
}
我的问题是当我开始第二个文件传输时,第一个文件的进度条会停止,而第二个传输的进度条会发疯,显示随机值,增加和减少。我的猜测是以某种方式添加了第一个文件的进度。
不知何故,我无法将每个进度条的进度分开。
我做错了什么?
【问题讨论】:
标签: c# wpf progress-bar ssh.net