下午好。我正在Windows窗体上制作一个应用程序。因为我正在为过渡到WPF和MVVM做心理准备,所以我决定首先在熟悉的环境中尝试这种模式。我请您评估我处理绑定和异步方法的能力。
public partial class MainForm : Form
{
ViewModel vm;
public MainForm()
{
InitializeComponent();
//----bindings
vm = new ViewModel();
vm.Message += (s, msg) => MessageBox.Show(msg);
tbArchieve.DataBindings.Add(new Binding("Text", vm, "ArchieveName", false, DataSourceUpdateMode.OnPropertyChanged));
tbDestinationFolder.DataBindings.Add(new Binding("Text", vm, "DestinationFolder", false, DataSourceUpdateMode.OnPropertyChanged));
btStart.DataBindings.Add(new Binding("Enabled", vm, "Ready"));
pbExtraction.DataBindings.Add(new Binding("Value", vm, "Progress"));
}
private void btBrowseFile_Click(object sender, EventArgs e)
{
using (OpenFileDialog dialog = new OpenFileDialog())
{
dialog.Filter = "Архивы|*.7z;*.rar;*.zip";
if(dialog.ShowDialog() == DialogResult.OK)
{
vm.ArchieveName = dialog.FileName;
}
}
}
private void btBrowserDistrination_Click(object sender, EventArgs e)
{
using (FolderBrowserDialog dialog = new FolderBrowserDialog())
{
dialog.SelectedPath = Application.ExecutablePath;
if(dialog.ShowDialog() == DialogResult.OK)
{
vm.DestinationFolder = dialog.SelectedPath;
}
}
}
private void btStart_Click(object sender, EventArgs e)
{
vm.Start();
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<string> Message;
private void OnPropertyChanged(params string[] props)
{
foreach (var p in props)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}
}
public ViewModel()
{
_destinationFolder = string.Empty;
_archieveName = string.Empty;
}
#region Поля для формы
string _archieveName;
public string ArchieveName
{
get
{ return _archieveName; }
set
{
if(_archieveName!= value)
{
_archieveName = value;
OnPropertyChanged("ArchieveName","Ready");
}
}
}
string _destinationFolder;
public string DestinationFolder
{
get
{ return _destinationFolder; }
set
{
if (_destinationFolder != value)
{
_destinationFolder = value;
OnPropertyChanged("DestinationFolder", "Ready");
}
}
}
int _progress;
public int Progress
{
get
{
return _progress;
}
set
{
if(_progress!=value)
{
_progress = value;
OnPropertyChanged("Progress");
}
}
}
public bool Ready
{
get
{
if(File.Exists(_archieveName))
{
if(IsValidPath(_destinationFolder))
{
return true;
}
}
return false;
}
}
private bool IsValidPath(string path)
{
var empty = string.IsNullOrWhiteSpace(path);
var wrongsyms = path.IndexOfAny(new char[] { '<', '>', '?', '*' }) != -1;
if (empty || wrongsyms)
{
return false;
}
return true;
}
#endregion
public async void Start()
{
Unpacker unpacker = new Unpacker(_archieveName);
unpacker.FileExtracted += (s, ea) => Progress = ea.PercentDone;
try
{
await unpacker.ExtractArchieve(_destinationFolder);
}
catch(Exception e)
{
Message.Invoke(this, e.Message);
}
Message?.Invoke(this, "Архив извлечен!");
}
}
public class Unpacker
{
SevenZipExtractor extractor;
public async Task ExtractArchieve(string dstFolder)
{
await extractor.ExtractArchiveAsync(dstFolder);
}
public Unpacker(string fileName)
{
extractor = new SevenZipExtractor(fileName);
extractor.FileExtractionFinished += Extractor_FileExtractionFinished;
}
public event EventHandler<FileInfoEventArgs> FileExtracted;
private void Extractor_FileExtractionFinished(object sender, FileInfoEventArgs e)
{
FileExtracted?.Invoke(this, e);
}
}
还有一个问题-如果窗体上的控件绑定到的ViewModel中的属性从异步方法更改,如何做正确的事情。提前感谢!
我看了很多例子,但我不明白
1条答案
按热度按时间vatpfxk51#
有几件事引起了我的注意(但老实说,我不是这方面的Maven):
WinForms设计器支持数据绑定,所以你只需要在设计器中把绑定放在一起,指定视图模型的类型(它应该作为属性提供,因此将字段
vm
更改为属性)。INotifyPropertyChanged
通常是这样实现的:这允许你像这样定义你的属性: