using Prism.Mvvm; using System; using System.Globalization; using System.Linq; using XP.ImageProcessing.Core; namespace XplorePlane.ViewModels { public class ProcessorParameterVM : BindableBase { private object _value; private bool _isValueValid = true; public ProcessorParameterVM(ProcessorParameter parameter) { Name = parameter.Name; DisplayName = parameter.DisplayName; _value = parameter.Value; MinValue = parameter.MinValue; MaxValue = parameter.MaxValue; Options = parameter.Options; ParameterType = parameter.ValueType?.Name?.ToLowerInvariant() switch { "int32" or "int" => "int", "double" => "double", "boolean" or "bool" => "bool", _ => "enum" }; ValidateValue(_value); } public string Name { get; } public string DisplayName { get; } public object MinValue { get; } public object MaxValue { get; } public string[]? Options { get; } public string ParameterType { get; } public bool IsValueValid { get => _isValueValid; private set => SetProperty(ref _isValueValid, value); } public object Value { get => _value; set { var normalizedValue = NormalizeValue(value); if (SetProperty(ref _value, normalizedValue)) ValidateValue(normalizedValue); } } private void ValidateValue(object value) { if (value == null) { IsValueValid = false; return; } if (ParameterType == "int") { IsValueValid = TryConvertToInt(value, out var intValue) && IsWithinRange(intValue); return; } if (ParameterType == "double") { IsValueValid = TryConvertToDouble(value, out var doubleValue) && IsWithinRange(doubleValue); return; } if (ParameterType == "bool") { IsValueValid = TryConvertToBool(value, out _); return; } if (Options is { Length: > 0 }) { var stringValue = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty; IsValueValid = Options.Contains(stringValue, StringComparer.OrdinalIgnoreCase); return; } IsValueValid = true; } private object NormalizeValue(object value) { if (value == null) return value; if (ParameterType == "int" && TryConvertToInt(value, out var intValue)) return intValue; if (ParameterType == "double" && TryConvertToDouble(value, out var doubleValue)) return doubleValue; if (ParameterType == "bool" && TryConvertToBool(value, out var boolValue)) return boolValue; return value; } private bool IsWithinRange(double value) { if (MinValue != null && TryConvertToDouble(MinValue, out var minValue) && value < minValue) return false; if (MaxValue != null && TryConvertToDouble(MaxValue, out var maxValue) && value > maxValue) return false; return true; } private static string NormalizeNumericText(string value) { return value.Trim().TrimEnd('、', ',', ',', '。', '.', ';', ';', ':', ':'); } private static bool TryConvertToInt(object value, out int result) { switch (value) { case int intValue: result = intValue; return true; case string stringValue: stringValue = NormalizeNumericText(stringValue); return int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out result) || int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.CurrentCulture, out result); default: try { result = Convert.ToInt32(value, CultureInfo.InvariantCulture); return true; } catch { result = default; return false; } } } private static bool TryConvertToDouble(object value, out double result) { switch (value) { case double doubleValue: result = doubleValue; return true; case float floatValue: result = floatValue; return true; case int intValue: result = intValue; return true; case long longValue: result = longValue; return true; case string stringValue: stringValue = NormalizeNumericText(stringValue); return double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result) || double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out result); default: try { result = Convert.ToDouble(value, CultureInfo.InvariantCulture); return true; } catch { result = default; return false; } } } private static bool TryConvertToBool(object value, out bool result) { switch (value) { case bool boolValue: result = boolValue; return true; case string stringValue: return bool.TryParse(stringValue.Trim(), out result); default: try { result = Convert.ToBoolean(value, CultureInfo.InvariantCulture); return true; } catch { result = default; return false; } } } } }