如果纬度或经度格式不正确,则显示错误



我的WPF应用程序有一个对话框,用户可以在其中输入纬度&一个经度。我已经编写了一个IValueConverter,它可以处理以十进制度或度-分-秒格式输入的值:

[ValueConversion( typeof( double? ), typeof( string ) )]
public class CoordinateConverter : IValueConverter {
    #region IValueConverter Members
    public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) {
        double angle = 0.0;
        if ( value is string ) {
            if ( !double.TryParse( value as string, NumberStyles.Float, CultureInfo.InvariantCulture, out angle ) ) {
                return value;
            }
        } else if ( value is double || value is double? ) {
            angle = (double) value;
        } else {
            return value.ToString();
        }
        bool isNegative = angle < 0;
        if ( isNegative ) angle = -angle;
        double degrees   = Math.Truncate( angle );
        double remainder = ( angle - degrees ) * 60.0;
        double minutes   = Math.Truncate( remainder );
        double seconds   = ( remainder - minutes ) * 60.0;
        string result = degrees.ToString( "##0", culture.NumberFormat ) + "° " +
                        minutes.ToString( "#0", culture.NumberFormat ) + "' " +
                        seconds.ToString( "#0.00", culture.NumberFormat ) + "" ";
        // The parameter contains "NS" for Latitudes and "EW" for Longitudes.
        if ( parameter != null ) {
            result += ( (string) parameter ).Substring( ( isNegative ? 1 : 0 ), 1 );
        } else {
            result = ( isNegative ? "-" : string.Empty ) + result;
        }
        return result;
    }
    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) {
        string strValue = value as string;
        if ( string.IsNullOrEmpty( strValue ) ) {
            return null;
        }
        double adjustForSign = 1.0;
        if ( strValue.IndexOf( "-" ) >= 0 ) {
            adjustForSign = -1.0;
            strValue = strValue.Substring( strValue.IndexOf( "-" ) + 1 );
        }
        // Parse the value in the field.  It's in three parts:  Degrees, minutes & seconds
        int degreeSymbol = strValue.IndexOf( "°" );
        int minuteSymbol = strValue.IndexOf( "'" );
        int secondSymbol = strValue.IndexOf( '"' );
        string degrees = null, minutes = null, seconds = null;
        double angle, d, m, s;
        if ( degreeSymbol < 0 ) {
            if ( double.TryParse( strValue, NumberStyles.Number, culture.NumberFormat, out angle ) ) {
                return angle;
            } else {
                return value;
            }
        } else {
            degrees = strValue.Substring( 0, degreeSymbol );
            if ( minuteSymbol >= 0 ) {
                minutes = strValue.Substring( degreeSymbol + 2, minuteSymbol - degreeSymbol - 2 );
            }
            if ( secondSymbol < 0 ) {
                seconds = "0" + culture.NumberFormat.NumberDecimalSeparator + "0";
            } else {
                seconds = strValue.Substring( minuteSymbol + 2, secondSymbol - minuteSymbol - 2 );
            }
        }
        if ( !double.TryParse( degrees, NumberStyles.Integer, culture.NumberFormat, out d ) ) return value;
        if ( !double.TryParse( minutes, NumberStyles.Integer, culture.NumberFormat, out m ) ) return value;
        if ( !double.TryParse( seconds, NumberStyles.Float  , culture.NumberFormat, out s ) ) return value;
        angle = d + m / 60.0 + s / 3600.0;
        if ( parameter != null ) {
            if ( strValue.Contains( ( (string) parameter ).Substring( 1, 1 ) ) ) {
                angle = -angle;
            }
        } else {
            angle *= adjustForSign;
        }
        return angle;
    }

在对话框中,我使用这个ControlTemplate来显示错误:

<ControlTemplate x:Key="InputErrorTemplate">
    <DockPanel LastChildFill="True">
        <Image DockPanel.Dock="Right"
               Height="20"
               Margin="-30,0,0,0"
               Source="{StaticResource ErrorImage}"
               ToolTip="{x:Static res:Car.Common_InvalidData}"
               VerticalAlignment="Center"
               Width="20" />
        <Border BorderBrush="Red"
                BorderThickness="5"
                Margin="5,0,30,0">
            <AdornedElementPlaceholder />
        </Border>
    </DockPanel>
</ControlTemplate>

如果其中一个TextBoxes中有一个字符串,它不会解析,不会抛出异常,并且显示我的对话框的错误模板。当我将鼠标悬停在TextBox上时,显示的错误信息是"输入字符串格式不正确"

我有几个问题:

  1. 错误信息来自哪里?它不在我的代码中,如果转换器抛出异常,程序就会因为未处理而死亡。
  2. 最后,如果无法解析TextBox中的值,我想显示一个错误。对话框的视图模型对象确实实现了IDataErrorInfo,但从字符串到双精度的转换不是由该对象完成的。我该怎么做呢?

由于文本框可能在代码隐藏中绑定到双属性,我认为有一些聪明的预转换验证,它给出了您看到的验证错误。要控制验证过程,我认为有几种方法:

  • 您可以创建自己的验证规则
  • 你可以从转换器返回一个验证结果(尽管在IMO验证和转换似乎并不属于一起)
  • 你可以利用IDataError接口和MVVM

这里有几个链接,提供了一些很好的信息:

  • 使用ViewModel提供有意义的验证错误消息
  • WPF中的数据验证
  • 在WPF中使用自定义验证规则

还有一件事,当将输入转换为double类型时,是否有特殊的原因使用不变区域性而不是作为参数传递的区域性?它可能在非英语文化(例如丹麦语)中失败,其中小数分隔符是逗号(相当于英语文化中的千位分隔符)。

在玩了一段时间后,我发现绑定似乎试图根据数据流动的方向将ConvertConvertBack方法返回的任何值转换为正确的类型。如果不能将值转换为该类型,则会将"输入字符串格式不正确"消息添加到该控件的错误集合中。如果我的代码只返回原始值不变如果有问题,我最终会得到那个消息。

这个消息已经足够好了,至少现在是这样。如果我想要一个不同的消息,我将不得不研究创建一个验证规则或一些其他机制。

相关内容

最新更新