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.
 
 
 
 

352 lines
11 KiB

using Avalonia.Media;
using Avalonia.Threading;
using HeroIconsAvalonia.Enums;
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 : ReactiveObject
{
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;
public DialogHostPageViewModel()
{
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;
}
}
}