164 lines
4.6 KiB
C#
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;
|
|
}
|
|
}
|
|
|