Files

164 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
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;
namespace WxOrder.Framework.Commons;
public enum InputType
{
Text, // 任意文本
Integer, // 整数
Decimal // 小数
}
/// <summary>
/// InputDialog.xaml 的交互逻辑
/// </summary>
public partial class InputDialog : Window
{
private readonly InputType _type;
private readonly bool _allowEmpty;
// 输入过程中允许的"部分输入"格式(如 "-"、"1." 也允许)
private static readonly Regex IntPartial = new(@"^-?\d*$");
private static readonly Regex DecPartial = new(@"^-?\d*\.?\d*$");
/// <summary>用户输入的原始文本</summary>
public string ResultText { get; private set; } = "";
private InputDialog(Window? owner, string title, string prompt,
string defaultValue, InputType type, bool allowEmpty)
{
InitializeComponent();
Owner = owner ?? Application.Current.Windows
.OfType<Window>()
.FirstOrDefault(w => w.IsActive) ?? Application.Current.MainWindow;
if (Owner == null) WindowStartupLocation = WindowStartupLocation.CenterScreen;
Title = title;
PromptText.Text = prompt;
InputBox.Text = defaultValue;
_type = type;
_allowEmpty = allowEmpty;
// 粘贴时同样校验
DataObject.AddPastingHandler(InputBox, (s, e) =>
{
if (_type == InputType.Text) return;
if (e.DataObject.GetData(DataFormats.Text) is not string pasted ||
!IsPartialValid(Preview(pasted)))
e.CancelCommand();
});
}
private void Window_ContentRendered(object? sender, EventArgs e)
{
InputBox.Focus();
InputBox.SelectAll();
}
// 按键输入时实时限制字符
private void InputBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
if (_type == InputType.Text) return;
e.Handled = !IsPartialValid(Preview(e.Text));
}
// 计算输入/粘贴后的文本
private string Preview(string incoming)
{
var t = InputBox.Text;
return t.Remove(InputBox.SelectionStart, InputBox.SelectionLength)
.Insert(InputBox.SelectionStart, incoming);
}
private bool IsPartialValid(string text) => _type switch
{
InputType.Integer => IntPartial.IsMatch(text),
InputType.Decimal => DecPartial.IsMatch(text),
_ => true
};
private void Ok_Click(object sender, RoutedEventArgs e)
{
var text = InputBox.Text.Trim();
if (text.Length == 0 && !_allowEmpty)
{
ShowError("内容不能为空");
return;
}
if (text.Length > 0)
{
if (_type == InputType.Integer && !int.TryParse(text, NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture, out _))
{
ShowError("请输入有效的整数");
return;
}
if (_type == InputType.Decimal && !double.TryParse(text, NumberStyles.Float,
CultureInfo.InvariantCulture, out _))
{
ShowError("请输入有效的数字");
return;
}
}
ResultText = text;
DialogResult = true;
}
private void ShowError(string msg)
{
ErrorText.Text = msg;
ErrorText.Visibility = Visibility.Visible;
InputBox.Focus();
InputBox.SelectAll();
}
// ================= 静态帮助方法 =================
/// <summary>输入文本。取消返回 null。</summary>
public static string? ShowText(string prompt, string title = "输入",
string defaultValue = "", bool allowEmpty = false, Window? owner = null)
{
var dlg = new InputDialog(owner, title, prompt, defaultValue, InputType.Text, allowEmpty);
return dlg.ShowDialog() == true ? dlg.ResultText : null;
}
/// <summary>输入整数。取消返回 null。</summary>
public static int? ShowInt(string prompt, string title = "输入",
int? defaultValue = null, Window? owner = null)
{
var dlg = new InputDialog(owner, title, prompt,
defaultValue?.ToString(CultureInfo.InvariantCulture) ?? "", InputType.Integer, false);
return dlg.ShowDialog() == true
? int.Parse(dlg.ResultText, CultureInfo.InvariantCulture)
: null;
}
/// <summary>输入小数。取消返回 null。</summary>
public static double? ShowDouble(string prompt, string title = "输入",
double? defaultValue = null, Window? owner = null)
{
var dlg = new InputDialog(owner, title, prompt,
defaultValue?.ToString(CultureInfo.InvariantCulture) ?? "", InputType.Decimal, false);
return dlg.ShowDialog() == true
? double.Parse(dlg.ResultText, CultureInfo.InvariantCulture)
: null;
}
}