Wednesday, March 31, 2010

DMS Value Converter for Silverlight/WPF

Longitudes, latitudes and other angular measurements are normally stored as decimals degrees such as 10.25.  However angles most commonly displayed as degrees minutes and second, for example, 10°15’00”.  This post contains code for a simple application that demonstrates a decimal degrees to degrees minutes seconds value converter.  The converter is defined in code but applied in XAML for any Silverlight or WPF application.

In this example, the code is for the following WPF windows application:

DMS Value Converter

In the code behind for the window looks like this:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace DmsConverterSample {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }
    }

    [ValueConversion(typeof(string), typeof(string))]
    public class DmsConverter : IValueConverter {
        public object Convert(object value,
                              Type targetType,
                              object parameter,
                              CultureInfo culture) {
            // Test for Null
            if (value == null) { return "Null"; }
            string st = value.ToString();
            if (string.IsNullOrEmpty(st)) { return "Empty"; }

            // Get Angle
            double angle;
            if (!double.TryParse(st, out angle)) { return "Not an angle"; }

            // Set flag if number is negative
            bool neg = angle < 0d;

            // Work with a positive number
            angle = Math.Abs(angle);

            // Get d/m/s components
            double d = Math.Floor(angle);
            angle -= d;
            angle *= 60;
            double m = Math.Floor(angle);
            angle -= m;
            angle *= 60;
            double s = Math.Round(angle);

            // Format
            return string.Format("{0:00}°{1:00}'{2:00}\"", d, m, s);
        }
        public object ConvertBack(object value,
                                  Type targetType,
                                  object parameter,
                                  CultureInfo culture) {
            throw new NotImplementedException();
        }
    }
}

And the XAML is here:

<Window x:Class="DmsConverterSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DmsConverterSample"
        Title="Convert from DD to DMS"
        Height="150"
        Width="400">
    <Grid Margin="5,5,5,5">
        <Grid.Resources>
            <local:DmsConverter x:Key="DmsConverter"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="3"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0"
                   Grid.Row="0"
                   Text="Decimal Degrees" />
        <TextBlock Grid.Column="0"
                   Grid.Row="1"
                   Text="Degrees Minutes Seconds"/>
        <TextBox x:Name="DD" Grid.Column="2" Grid.Row="0"/>
        <TextBox x:Name="DMS"
                 Grid.Column="2"
                 Grid.Row="1"
                 IsEnabled="False"
                 Text="{Binding
                    ElementName=DD,
                    Path=Text,
                    Mode=OneWay,
                    Converter={StaticResource ResourceKey=DmsConverter}}"
                 />
    </Grid>
</Window>

This samples utilises element binding.  As you type an angle in decimal degrees, the angle will automatically be converted to degrees minutes seconds in the second text box.

1 comment: