diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj index 3cd6540..4bbb6e9 100644 --- a/TransportPlugin.csproj +++ b/TransportPlugin.csproj @@ -307,6 +307,7 @@ + diff --git a/src/UI/WPF/Converters/EditableNumberConverter.cs b/src/UI/WPF/Converters/EditableNumberConverter.cs new file mode 100644 index 0000000..ee7886a --- /dev/null +++ b/src/UI/WPF/Converters/EditableNumberConverter.cs @@ -0,0 +1,127 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace NavisworksTransport.UI.WPF.Converters +{ + /// + /// Keeps numeric TextBox editing humane: incomplete text is allowed while editing, + /// and only complete numeric values are written back to the bound source. + /// + public class EditableNumberConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + { + return string.Empty; + } + + string format = parameter as string; + if (string.IsNullOrWhiteSpace(format)) + { + return System.Convert.ToString(value, culture); + } + + if (value is IFormattable formattable) + { + return formattable.ToString(format, culture); + } + + return System.Convert.ToString(value, culture); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + string text = value as string; + if (IsIntermediateText(text)) + { + throw new FormatException("请输入有效的数字。"); + } + + text = text.Trim(); + Type actualTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType; + + if (TryParseNumber(text, culture, actualTargetType, out object parsedValue)) + { + return parsedValue; + } + + throw new FormatException("请输入有效的数字。"); + } + + public static bool IsIntermediateText(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return true; + } + + text = text.Trim(); + + return text == "-" || + text == "+" || + text == "." || + text == "-." || + text == "+."; + } + + public static bool TryParseNumber(string text, CultureInfo culture, Type targetType, out object parsedValue) + { + NumberStyles styles = NumberStyles.Float | NumberStyles.AllowThousands; + + if (targetType == typeof(double)) + { + if (TryParseDouble(text, styles, culture, out double doubleValue)) + { + parsedValue = doubleValue; + return true; + } + } + else if (targetType == typeof(float)) + { + if (TryParseDouble(text, styles, culture, out double doubleValue)) + { + parsedValue = (float)doubleValue; + return true; + } + } + else if (targetType == typeof(decimal)) + { + if (decimal.TryParse(text, styles, culture, out decimal decimalValue) || + decimal.TryParse(text, styles, CultureInfo.InvariantCulture, out decimalValue)) + { + parsedValue = decimalValue; + return true; + } + } + else if (targetType == typeof(int)) + { + if (int.TryParse(text, NumberStyles.Integer, culture, out int intValue) || + int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out intValue)) + { + parsedValue = intValue; + return true; + } + } + else if (targetType == typeof(long)) + { + if (long.TryParse(text, NumberStyles.Integer, culture, out long longValue) || + long.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue)) + { + parsedValue = longValue; + return true; + } + } + + parsedValue = null; + return false; + } + + private static bool TryParseDouble(string text, NumberStyles styles, CultureInfo culture, out double value) + { + return double.TryParse(text, styles, culture, out value) || + double.TryParse(text, styles, CultureInfo.InvariantCulture, out value); + } + } +} diff --git a/src/UI/WPF/Views/AnimationControlView.xaml b/src/UI/WPF/Views/AnimationControlView.xaml index f6226aa..eb9efcb 100644 --- a/src/UI/WPF/Views/AnimationControlView.xaml +++ b/src/UI/WPF/Views/AnimationControlView.xaml @@ -27,6 +27,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 +