public static async Task DownloadFileAsync(string url, string destination) { var downloadFile = new DownloadFile(); // frustratingly copy pasta from wireUpEvents(IDownloadable downloadable) due to Completed being EventHandler<LibraryBook> var downloadDialog = new DownloadForm(); downloadFile.DownloadBegin += (_, str) => { downloadDialog.UpdateFilename(str); downloadDialog.Show(); }; downloadFile.DownloadProgressChanged += (_, progress) => downloadDialog.DownloadProgressChanged(progress.BytesReceived, progress.TotalBytesToReceive); downloadFile.DownloadCompleted += (_, __) => downloadDialog.Close(); await downloadFile.PerformDownloadFileAsync(url, destination); }
// subscribed to Begin event because a new form should be created+processed+closed on each iteration private static void wireUpEvents(IDownloadableProcessable downloadable) { #region create form var downloadDialog = new DownloadForm(); #endregion // extra complexity for wiring up download form: // case 1: download is needed // dialog created. subscribe to events // downloadable.DownloadBegin fires. shows dialog // downloadable.DownloadCompleted fires. closes dialog. which fires FormClosing, FormClosed, Disposed // Disposed unsubscribe from events // case 2: download is not needed // dialog created. subscribe to events // dialog is never shown nor closed // downloadable.Completed fires. disposes dialog and unsubscribes from events #region define how model actions will affect form behavior void downloadBegin(object _, string str) { downloadDialog.UpdateFilename(str); downloadDialog.Show(); } // close form on DOWNLOAD completed, not final Completed. Else for BackupBook this form won't close until DECRYPT is also complete void fileDownloadCompleted(object _, string __) => downloadDialog.Close(); void downloadProgressChanged(object _, Dinah.Core.Net.Http.DownloadProgress progress) => downloadDialog.DownloadProgressChanged(progress.BytesReceived, progress.TotalBytesToReceive); void unsubscribe(object _ = null, EventArgs __ = null) { downloadable.DownloadBegin -= downloadBegin; downloadable.DownloadCompleted -= fileDownloadCompleted; downloadable.DownloadProgressChanged -= downloadProgressChanged; downloadable.Completed -= dialogDispose; } // unless we dispose, if the form is created but un-used/never-shown then weird UI stuff can happen // also, since event unsubscribe occurs on FormClosing and an unused form is never closed, then the events will never be unsubscribed void dialogDispose(object _, object __) { if (!downloadDialog.IsDisposed) { downloadDialog.Dispose(); } } #endregion #region subscribe new form to model's events downloadable.DownloadBegin += downloadBegin; downloadable.DownloadCompleted += fileDownloadCompleted; downloadable.DownloadProgressChanged += downloadProgressChanged; downloadable.Completed += dialogDispose; #endregion #region when form closes, unsubscribe from model's events // unsubscribe so disposed forms aren't still trying to receive notifications // FormClosing is more UI safe but won't fire unless the form is shown and closed // if form was shown, Disposed will fire for FormClosing, FormClosed, and Disposed // if not shown, it will still fire for Disposed downloadDialog.Disposed += unsubscribe; #endregion }