using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; 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 的交互逻辑 /// internal partial class CopyableBox : Window, IDisposable { private CopyableBoxViewModel ViewModel => (CopyableBoxViewModel)DataContext; public CopyableBox(Window owner, string title, Func> action) { InitializeComponent(); Owner = owner; ViewModel.Initialize(title, action, Dispatcher); } public void Dispose() { ViewModel.Dispose(); } private async void ClosingHandler(object sender, CancelEventArgs e) { if (ViewModel.ReadyToClose) { return; } e.Cancel = true; await Dispatcher.Yield(); if (ViewModel.CloseCommand.CanExecuteValue) { ViewModel.CloseCommand.Execute(this); } return; } } internal class CopyableBoxViewModel : NotifyPropertyChanged, IDisposable { private readonly CancellationTokenSource _cancellationTokenSource = new(); private Task? _task; private string _title = "我居然没有名字qwq"; public string Title { get => _title; private set => SetField(ref _title, value); } private const string InitialMessage = "正在加载…… 关闭窗口就可以取消加载("; private string _text = InitialMessage; public string Text { get => _text; private set => SetField(ref _text, value); } public string CloseButtonText => CloseCommand.CanExecuteValue ? "关闭窗口" : "正在关闭…"; private bool _readyToClose = false; public bool ReadyToClose { get => _readyToClose; private set => SetField(ref _readyToClose, value); } public Command CopyCommand { get; } public Command CloseCommand { get; } public CopyableBoxViewModel() { CopyCommand = new Command(() => { Clipboard.SetText(Text); return Task.CompletedTask; }); CloseCommand = new Command(async window => { CloseCommand!.CanExecuteValue = false; Notify(nameof(CloseButtonText)); if (_task != null) { try { Cancel(); await _task; } catch (OperationCanceledException) { } } ReadyToClose = true; window.Close(); }); } public void Dispose() { Cancel(); _cancellationTokenSource.Dispose(); } public void Initialize(string title, Func> action, Dispatcher dispatcher) { Title = title; _task = InitializationTask(action, dispatcher); } private async Task InitializationTask(Func> action, Dispatcher dispatcher) { var token = _cancellationTokenSource.Token; async Task Action() { try { using var timer = new DisposableDispatcherTimer(timer => { Text = $"{InitialMessage}\r\n目前耗时{timer.TimeSinceCreation},稍微再等一下吧233"; }, dispatcher, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(1)); return await action(token); } catch (OperationCanceledException) { return "操作已被取消"; } } Text = await dispatcher.Invoke(Action); } private void Cancel() { _cancellationTokenSource.Cancel(); } } }