diff --git a/Controller.cs b/Controller.cs index 54c57e4..cbbf855 100644 --- a/Controller.cs +++ b/Controller.cs @@ -42,7 +42,7 @@ namespace HashCalculator.GUI { case InputEntryType.BinaryFile: ViewModel.StatusText = "请留意一下弹出的窗口("; - CopyableBox.ShowDialog("SAGE FastHash 计算器", token => CalculateBinaryHash(selected.Value, token)); + await ViewModel.RequestCopyableBox("SAGE FastHash 计算器", token => CalculateBinaryHash(selected.Value, token)); ViewModel.StatusText = string.Empty; return; case InputEntryType.BigFile: @@ -62,7 +62,7 @@ namespace HashCalculator.GUI catch (Exception error) { ViewModel.StatusText = "失败…"; - CopyableBox.ShowDialog("SAGE FastHash 计算器 - 失败!", _ => + await ViewModel.RequestCopyableBox("SAGE FastHash 计算器 - 失败!", _ => { return Task.FromResult($"在尝试加载 {selected.Type} `{selected.Value}` 时发生错误:\r\n{error}"); }); @@ -313,7 +313,7 @@ namespace HashCalculator.GUI } } - public static async Task LoadCsf(string filePath) + public async Task LoadCsf(string filePath) { await ExceptionWrapepr(async () => { @@ -417,7 +417,22 @@ namespace HashCalculator.GUI UpdateEntries(); } - public static IEnumerable FindManifests() + private async Task ExceptionWrapepr(Func action, string errorTitle, string preErrorMessage) + { + try + { + await action().ConfigureAwait(true); + } + catch (Exception exception) + { + await ViewModel.RequestCopyableBox(errorTitle, _ => + { + return Task.FromResult(preErrorMessage + exception); + }); + } + } + + private static IEnumerable FindManifests() { var manifests = VirtualFileSystem.ListFiles(SelectedFileSystemRootPath, "*.manifest", VirtualSearchOptionType.AllDirectories); var modManifests = from manifest in manifests @@ -439,20 +454,5 @@ namespace HashCalculator.GUI { return VirtualFileSystem.GetFileName(path).StartsWith(what, StringComparison.OrdinalIgnoreCase); } - - private static async Task ExceptionWrapepr(Func action, string errorTitle, string preErrorMessage) - { - try - { - await action().ConfigureAwait(true); - } - catch (Exception exception) - { - CopyableBox.ShowDialog(errorTitle, _ => - { - return Task.FromResult(preErrorMessage + exception); - }); - } - } } } diff --git a/CopyableBox.xaml.cs b/CopyableBox.xaml.cs index 5303c40..a2a6ad4 100644 --- a/CopyableBox.xaml.cs +++ b/CopyableBox.xaml.cs @@ -1,43 +1,39 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; using System.Windows.Threading; -using TechnologyAssembler.Core.Extensions; namespace HashCalculator.GUI { + public class ShowCopyableBoxEventArgs : EventArgs + { + public string Title { get; } + public Func> GetContent { get; } + public Task Completion { get; set; } + + public ShowCopyableBoxEventArgs(string title, Func> getContent) + { + Title = title; + GetContent = getContent; + Completion = Task.CompletedTask; + } + } + /// /// CopyableBox.xaml 的交互逻辑 /// - [SuppressMessage("Microsoft.Performance", "CA1812")] internal partial class CopyableBox : Window, IDisposable { private CopyableBoxViewModel ViewModel => (CopyableBoxViewModel)DataContext; - public static void ShowDialog(string title, Func> action) - { - using var box = new CopyableBox(); - box.ViewModel.Initialize(title, action, box.Dispatcher); - box.Owner = App.Current.MainWindow; - box.ShowDialog(); - } - - private CopyableBox() + public CopyableBox(Window owner, string title, Func> action) { InitializeComponent(); + Owner = owner; + ViewModel.Initialize(title, action, Dispatcher); } public void Dispose() @@ -45,7 +41,7 @@ namespace HashCalculator.GUI ViewModel.Dispose(); } - private void ClosingHandler(object sender, CancelEventArgs e) + private async void ClosingHandler(object sender, CancelEventArgs e) { if (ViewModel.ReadyToClose) { @@ -53,19 +49,18 @@ namespace HashCalculator.GUI } e.Cancel = true; + await Dispatcher.Yield(); if (ViewModel.CloseCommand.CanExecuteValue) { ViewModel.CloseCommand.Execute(this); } - return; } } - [SuppressMessage("Microsoft.Performance", "CA1812")] internal class CopyableBoxViewModel : NotifyPropertyChanged, IDisposable { - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancellationTokenSource = new(); private Task? _task; private string _title = "我居然没有名字qwq"; @@ -113,13 +108,13 @@ namespace HashCalculator.GUI try { Cancel(); - await _task.ConfigureAwait(true); + await _task; } catch (OperationCanceledException) { } } ReadyToClose = true; - window.Close(); + window.Close(); }); } @@ -147,14 +142,14 @@ namespace HashCalculator.GUI Text = $"{InitialMessage}\r\n目前耗时{timer.TimeSinceCreation},稍微再等一下吧233"; }, dispatcher, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(1)); - return await action(token).ConfigureAwait(false); + return await action(token); } catch (OperationCanceledException) { return "操作已被取消"; } } - Text = await dispatcher.Invoke(Action).ConfigureAwait(true); + Text = await dispatcher.Invoke(Action); } private void Cancel() diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index df097c7..94be324 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -24,10 +24,22 @@ namespace HashCalculator.GUI { ViewModel.NotifyCsfChange(); }); + ViewModel.ShowCopyableBox += ViewModel_ShowCopyableBox; ViewModel.OpenFileDialog += ViewModel_OpenFileDialog; ViewModel.ClearTracer += ViewModel_ClearTracer; } + private void ViewModel_ShowCopyableBox(object? sender, ShowCopyableBoxEventArgs e) + { + var title = e.Title; + var getContent = e.GetContent; + e.Completion = Dispatcher.InvokeAsync(() => + { + using var box = new CopyableBox(this, title, getContent); + box.ShowDialog(); + }).Task; + } + private void ViewModel_OpenFileDialog(object? sender, OpenFileDialogEventArgs e) { var sdkRoot = new OpenFileDialog diff --git a/ViewModel.cs b/ViewModel.cs index 49f38e4..e7a3414 100644 --- a/ViewModel.cs +++ b/ViewModel.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Threading; using System.Threading.Tasks; using TechnologyAssembler.Core.IO; @@ -62,6 +63,7 @@ namespace HashCalculator.GUI { private static readonly Random _random = new(); public event EventHandler? ClearTracer; + public event EventHandler? ShowCopyableBox; public event EventHandler? OpenFileDialog; public MainInputViewModel MainInput { get; } public BigInputViewModel BigEntryInput { get; } @@ -120,8 +122,8 @@ namespace HashCalculator.GUI public bool IsXsd { get => _isXsd; - set => SetField(ref _isXsd, value, () => - { + set => SetField(ref _isXsd, value, () => + { IsXml |= value; ConsiderTypeId |= value; }); @@ -157,7 +159,7 @@ namespace HashCalculator.GUI var fileName = await controller.RequestOpenFile(string.Empty, ("*.csf;*.big", "CSF / BIG 文件")); if (fileName is not null) { - await Controller.LoadCsf(fileName).ConfigureAwait(true); + await controller.LoadCsf(fileName).ConfigureAwait(true); } } finally @@ -177,6 +179,13 @@ namespace HashCalculator.GUI }); } + public Task RequestCopyableBox(string title, Func> getContent) + { + var data = new ShowCopyableBoxEventArgs(title, getContent); + ShowCopyableBox?.Invoke(this, data); + return data.Completion; + } + public Task RequestOpenFile(string title, IEnumerable<(string Extension, string? Description)> filters) { var data = new OpenFileDialogEventArgs(title, filters); @@ -474,10 +483,10 @@ namespace HashCalculator.GUI } catch (Exception exception) { - CopyableBox.ShowDialog("SAGE FastHash 计算器的错误", _ => - { - return Task.FromResult($"在加载 manifest 时发生错误:{exception}"); - }); + await viewModel.RequestCopyableBox("SAGE FastHash 计算器的错误", _ => + { + return Task.FromResult($"在加载 manifest 时发生错误:{exception}"); + }); } finally {