You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
11 KiB
357 lines
11 KiB
using Avalonia.Media;
|
|
using Avalonia.Threading;
|
|
using HeroIconsAvalonia.Enums;
|
|
using MyAvaloniaApp.ViewModels.Base;
|
|
using ReactiveUI;
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Reactive;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace MyAvaloniaApp.ViewModels.Pages;
|
|
|
|
/// <summary>
|
|
/// DialogHost 示例页面的 ViewModel
|
|
/// </summary>
|
|
public class DialogHostPageViewModel : RoutableViewModel
|
|
{
|
|
private bool _isDialogOpen;
|
|
private string _dialogTitle = "提示";
|
|
private string _dialogMessage = "请选择需要执行的操作";
|
|
private string _lastActionMessage = string.Empty;
|
|
private bool _rememberChoice;
|
|
private bool _isRememberChoiceVisible = true;
|
|
private IconType _dialogIcon = IconType.InformationCircle;
|
|
private IBrush _dialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246));
|
|
private string _primaryButtonText = "确认";
|
|
private string _secondaryButtonText = "取消";
|
|
private bool _isPrimaryButtonVisible = true;
|
|
private bool _useAutoClose;
|
|
private TimeSpan _autoCloseDelay = TimeSpan.FromSeconds(2);
|
|
private CancellationTokenSource? _autoCloseCts;
|
|
|
|
/// <summary>
|
|
/// 构造函数
|
|
/// </summary>
|
|
/// <param name="hostScreen">宿主 Screen</param>
|
|
public DialogHostPageViewModel(IScreen hostScreen) : base(hostScreen, "DialogHost")
|
|
{
|
|
ShowDialogCommand = ReactiveCommand.Create<string?>(ShowDialog);
|
|
ConfirmDialogCommand = ReactiveCommand.Create(ConfirmDialog);
|
|
CancelDialogCommand = ReactiveCommand.Create(CancelDialog);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否展示对话框
|
|
/// </summary>
|
|
public bool IsDialogOpen
|
|
{
|
|
get => _isDialogOpen;
|
|
set => this.RaiseAndSetIfChanged(ref _isDialogOpen, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对话框标题
|
|
/// </summary>
|
|
public string DialogTitle
|
|
{
|
|
get => _dialogTitle;
|
|
set => this.RaiseAndSetIfChanged(ref _dialogTitle, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对话框消息
|
|
/// </summary>
|
|
public string DialogMessage
|
|
{
|
|
get => _dialogMessage;
|
|
set => this.RaiseAndSetIfChanged(ref _dialogMessage, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 记住选择
|
|
/// </summary>
|
|
public bool RememberChoice
|
|
{
|
|
get => _rememberChoice;
|
|
set => this.RaiseAndSetIfChanged(ref _rememberChoice, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 最近一次操作反馈
|
|
/// </summary>
|
|
public string LastActionMessage
|
|
{
|
|
get => _lastActionMessage;
|
|
set => this.RaiseAndSetIfChanged(ref _lastActionMessage, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对话框图标
|
|
/// </summary>
|
|
public IconType DialogIcon
|
|
{
|
|
get => _dialogIcon;
|
|
set => this.RaiseAndSetIfChanged(ref _dialogIcon, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对话框强调色
|
|
/// </summary>
|
|
public IBrush DialogAccentBrush
|
|
{
|
|
get => _dialogAccentBrush;
|
|
set => this.RaiseAndSetIfChanged(ref _dialogAccentBrush, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 主操作按钮文本
|
|
/// </summary>
|
|
public string PrimaryButtonText
|
|
{
|
|
get => _primaryButtonText;
|
|
set => this.RaiseAndSetIfChanged(ref _primaryButtonText, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 次操作按钮文本
|
|
/// </summary>
|
|
public string SecondaryButtonText
|
|
{
|
|
get => _secondaryButtonText;
|
|
set
|
|
{
|
|
this.RaiseAndSetIfChanged(ref _secondaryButtonText, value);
|
|
this.RaisePropertyChanged(nameof(HasSecondaryButton));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否展示次操作按钮
|
|
/// </summary>
|
|
public bool HasSecondaryButton => !string.IsNullOrWhiteSpace(_secondaryButtonText);
|
|
|
|
/// <summary>
|
|
/// 主操作按钮是否可见
|
|
/// </summary>
|
|
public bool IsPrimaryButtonVisible
|
|
{
|
|
get => _isPrimaryButtonVisible;
|
|
set => this.RaiseAndSetIfChanged(ref _isPrimaryButtonVisible, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否展示“记住选择”选项
|
|
/// </summary>
|
|
public bool IsRememberChoiceVisible
|
|
{
|
|
get => _isRememberChoiceVisible;
|
|
set => this.RaiseAndSetIfChanged(ref _isRememberChoiceVisible, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否启用自动关闭
|
|
/// </summary>
|
|
public bool UseAutoClose
|
|
{
|
|
get => _useAutoClose;
|
|
private set => this.RaiseAndSetIfChanged(ref _useAutoClose, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 自动关闭延时时间
|
|
/// </summary>
|
|
public TimeSpan AutoCloseDelay
|
|
{
|
|
get => _autoCloseDelay;
|
|
private set => this.RaiseAndSetIfChanged(ref _autoCloseDelay, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 展示对话框命令
|
|
/// </summary>
|
|
public ReactiveCommand<string?, Unit> ShowDialogCommand { get; }
|
|
|
|
/// <summary>
|
|
/// 确认操作命令
|
|
/// </summary>
|
|
public ReactiveCommand<Unit, Unit> ConfirmDialogCommand { get; }
|
|
|
|
/// <summary>
|
|
/// 取消操作命令
|
|
/// </summary>
|
|
public ReactiveCommand<Unit, Unit> CancelDialogCommand { get; }
|
|
|
|
private void ShowDialog(string? parameter)
|
|
{
|
|
CancelAutoCloseTimer();
|
|
|
|
var (variant, delayOverride) = ParseParameter(parameter);
|
|
ConfigureVariant(variant, delayOverride);
|
|
RememberChoice = false;
|
|
IsDialogOpen = true;
|
|
LastActionMessage = string.Empty;
|
|
|
|
if (UseAutoClose)
|
|
{
|
|
StartAutoCloseTimer();
|
|
}
|
|
}
|
|
|
|
private void ConfirmDialog()
|
|
{
|
|
CancelAutoCloseTimer();
|
|
IsDialogOpen = false;
|
|
var rememberSuffix = IsRememberChoiceVisible && RememberChoice ? "(记住选择)" : string.Empty;
|
|
LastActionMessage = $"已确认:{DialogTitle}{rememberSuffix}";
|
|
}
|
|
|
|
private void CancelDialog()
|
|
{
|
|
CancelAutoCloseTimer();
|
|
|
|
if (!HasSecondaryButton)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IsDialogOpen = false;
|
|
var rememberSuffix = IsRememberChoiceVisible && RememberChoice ? "(记住选择)" : string.Empty;
|
|
LastActionMessage = $"已取消:{DialogTitle}{rememberSuffix}";
|
|
}
|
|
|
|
private void ConfigureVariant(string? variant, TimeSpan? delayOverride)
|
|
{
|
|
var key = string.IsNullOrWhiteSpace(variant) ? "info" : variant.Trim().ToLowerInvariant();
|
|
|
|
UseAutoClose = false;
|
|
AutoCloseDelay = delayOverride ?? TimeSpan.FromSeconds(2);
|
|
IsPrimaryButtonVisible = true;
|
|
SecondaryButtonText = "取消";
|
|
PrimaryButtonText = "确认";
|
|
IsRememberChoiceVisible = true;
|
|
|
|
switch (key)
|
|
{
|
|
case "success":
|
|
DialogTitle = "操作成功";
|
|
DialogMessage = "所有任务都已顺利完成。您可以继续后续流程。";
|
|
DialogIcon = IconType.CheckCircle;
|
|
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(34, 197, 94));
|
|
PrimaryButtonText = string.Empty;
|
|
SecondaryButtonText = string.Empty;
|
|
IsRememberChoiceVisible = false;
|
|
IsPrimaryButtonVisible = false;
|
|
UseAutoClose = true;
|
|
break;
|
|
|
|
case "error":
|
|
case "failure":
|
|
DialogTitle = "操作失败";
|
|
DialogMessage = "执行过程中出现错误,请检查配置或稍后重试。";
|
|
DialogIcon = IconType.XCircle;
|
|
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(239, 68, 68));
|
|
PrimaryButtonText = string.Empty;
|
|
SecondaryButtonText = string.Empty;
|
|
IsRememberChoiceVisible = false;
|
|
IsPrimaryButtonVisible = false;
|
|
UseAutoClose = true;
|
|
break;
|
|
|
|
case "warning":
|
|
DialogTitle = "风险提示";
|
|
DialogMessage = "当前设置可能带来潜在风险,请在继续之前确认信息。";
|
|
DialogIcon = IconType.ExclamationTriangle;
|
|
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(234, 179, 8));
|
|
PrimaryButtonText = string.Empty;
|
|
SecondaryButtonText = string.Empty;
|
|
IsRememberChoiceVisible = false;
|
|
IsPrimaryButtonVisible = false;
|
|
UseAutoClose = true;
|
|
break;
|
|
|
|
case "confirm":
|
|
DialogTitle = "确认操作";
|
|
DialogMessage = "此操作会影响当前设置,请确认是否继续。";
|
|
DialogIcon = IconType.QuestionMarkCircle;
|
|
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246));
|
|
PrimaryButtonText = "确认";
|
|
SecondaryButtonText = "取消";
|
|
IsRememberChoiceVisible = false;
|
|
break;
|
|
|
|
case "info":
|
|
case "general":
|
|
default:
|
|
DialogTitle = "通用提示";
|
|
DialogMessage = "执行此操作将应用更改,是否继续?您也可以勾选记住选择。";
|
|
DialogIcon = IconType.InformationCircle;
|
|
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246));
|
|
PrimaryButtonText = "确认";
|
|
SecondaryButtonText = "取消";
|
|
IsRememberChoiceVisible = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private (string variant, TimeSpan? delayOverride) ParseParameter(string? parameter)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(parameter))
|
|
{
|
|
return ("info", null);
|
|
}
|
|
|
|
var parts = parameter.Split(new[] { ':', '|', ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
var variant = parts.Length > 0 ? parts[0].Trim() : "info";
|
|
|
|
if (parts.Length > 1 && double.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var seconds) && seconds > 0)
|
|
{
|
|
return (variant, TimeSpan.FromSeconds(seconds));
|
|
}
|
|
|
|
return (variant, null);
|
|
}
|
|
|
|
private void StartAutoCloseTimer()
|
|
{
|
|
CancelAutoCloseTimer();
|
|
|
|
var delay = AutoCloseDelay;
|
|
var titleSnapshot = DialogTitle;
|
|
|
|
_autoCloseCts = new CancellationTokenSource();
|
|
var token = _autoCloseCts.Token;
|
|
|
|
Task.Run(async () =>
|
|
{
|
|
try
|
|
{
|
|
await Task.Delay(delay, token);
|
|
if (!token.IsCancellationRequested)
|
|
{
|
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
|
{
|
|
IsDialogOpen = false;
|
|
LastActionMessage = $"已自动关闭:{titleSnapshot}";
|
|
});
|
|
}
|
|
}
|
|
catch (TaskCanceledException)
|
|
{
|
|
// 忽略取消
|
|
}
|
|
}, token);
|
|
}
|
|
|
|
private void CancelAutoCloseTimer()
|
|
{
|
|
if (_autoCloseCts != null)
|
|
{
|
|
_autoCloseCts.Cancel();
|
|
_autoCloseCts.Dispose();
|
|
_autoCloseCts = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
|