diff --git a/Docs/Images/logo-512.ico b/Docs/Images/logo-512.ico new file mode 100644 index 0000000000..9a363f02a5 Binary files /dev/null and b/Docs/Images/logo-512.ico differ diff --git a/README.md b/README.md index 887ed8c9cf..2c42bb64f7 100644 --- a/README.md +++ b/README.md @@ -121,12 +121,20 @@ RotationalSpeedUnit rpm2 == RotationalSpeed.ParseUnit("r/min"); // RotationalSp string abbrevKg = Mass.GetAbbreviation(MassUnit.Kilogram); // "kg" ``` -### Example: Creating a unit converter app +### Example: Creating a dynamic unit converter app -*TODO: Add actual sample app and link to it here with screenshot. See [#274](https://github.com/angularsen/UnitsNet/issues/274) for details.* +![image](https://user-images.githubusercontent.com/787816/34920961-9b697004-f97b-11e7-9e9a-51ff7142969b.png) + +See [Samples/UnitConverter.Wpf](https://github.com/angularsen/UnitsNet/tree/master/Samples/UnitConverter.Wpf) for source code. This example shows how you can create a dynamic unit converter, where the user selects the quantity to convert, such as `Length` or `Mass`, then selects to convert from `Meter` to `Centimeter` and types in a value for how many meters. +NOTE: There are still some limitations in the library that requires reflection to enumerate units for quantity and getting the abbreviation for a unit, when we want to dynamically enumerate and convert between units. + +### Example: Creating a unit converter app with hard coded quantities + +If you can live with hard coding what quantities to convert between, then the following code snippet shows you one way to go about it: + ```C# // Get quantities for populating quantity UI selector QuantityType[] quantityTypes = Enum.GetValues(typeof(QuantityType)).Cast().ToArray(); @@ -134,7 +142,12 @@ QuantityType[] quantityTypes = Enum.GetValues(typeof(QuantityType)).Cast + + + netcoreapp1.0 + ConsoleApp-NetCore + Exe + ConsoleApp-NetCore + 1.0.4 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + + diff --git a/Samples/ConsoleApp-NetCore/ConsoleApp-NetCore.xproj b/Samples/ConsoleApp-NetCore/ConsoleApp-NetCore.xproj deleted file mode 100644 index f136cf6d9e..0000000000 --- a/Samples/ConsoleApp-NetCore/ConsoleApp-NetCore.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 955a6cbf-c4e3-4c55-85c8-613e2ca4ccd7 - ConsoleApp - .\obj - .\bin\ - v4.5.2 - - - 2.0 - - - \ No newline at end of file diff --git a/Samples/ConsoleApp-NetCore/project.json b/Samples/ConsoleApp-NetCore/project.json deleted file mode 100644 index 7eaa22069c..0000000000 --- a/Samples/ConsoleApp-NetCore/project.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "1.0.0-*", - "buildOptions": { - "emitEntryPoint": true - }, - - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - }, - "UnitsNet": "3.45.0" - }, - - "frameworks": { - "netcoreapp1.0": { - "imports": "dnxcore50" - } - } -} diff --git a/Samples/Samples.sln b/Samples/Samples.sln index 649a44d2de..0d8fc0f162 100644 --- a/Samples/Samples.sln +++ b/Samples/Samples.sln @@ -1,9 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2020 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConsoleApp-NetCore", "ConsoleApp-NetCore\ConsoleApp-NetCore.xproj", "{955A6CBF-C4E3-4C55-85C8-613E2CA4CCD7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp-NetCore", "ConsoleApp-NetCore\ConsoleApp-NetCore.csproj", "{955A6CBF-C4E3-4C55-85C8-613E2CA4CCD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitConverter.Wpf", "UnitConverter.Wpf\UnitConverter.Wpf\UnitConverter.Wpf.csproj", "{D04EE35D-496A-4C83-A369-09B9B2BEAEEC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfMVVMSample", "WpfMVVMSample\WpfMVVMSample\WpfMVVMSample.csproj", "{B72F9215-70FF-4155-89BC-9A02CC550447}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,8 +19,19 @@ Global {955A6CBF-C4E3-4C55-85C8-613E2CA4CCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {955A6CBF-C4E3-4C55-85C8-613E2CA4CCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {955A6CBF-C4E3-4C55-85C8-613E2CA4CCD7}.Release|Any CPU.Build.0 = Release|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Release|Any CPU.Build.0 = Release|Any CPU + {B72F9215-70FF-4155-89BC-9A02CC550447}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B72F9215-70FF-4155-89BC-9A02CC550447}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B72F9215-70FF-4155-89BC-9A02CC550447}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B72F9215-70FF-4155-89BC-9A02CC550447}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A78FD611-C7A6-472D-95CA-4B474F775CCA} + EndGlobalSection EndGlobal diff --git a/Samples/UnitConverter.Wpf/README.md b/Samples/UnitConverter.Wpf/README.md new file mode 100644 index 0000000000..1c3e73e386 --- /dev/null +++ b/Samples/UnitConverter.Wpf/README.md @@ -0,0 +1,13 @@ +## Unit Converter WPF Sample App + +This is a simple sample showing how UnitsNet can be used to create a generic unit converter, using all the quantities and units available in the UnitsNet library. + +![image](https://user-images.githubusercontent.com/787816/34920961-9b697004-f97b-11e7-9e9a-51ff7142969b.png) + +It allows you to convert a value from one unit to another, by first selecting the quantity (`Length`), then selecting the from/to units (`Meter` to `Centimeter`) and finally typing the numeric value (`15.3`). +The resulting value (`1530`) is computed instantly and reacts to whenever the numeric value or the from/to unit selection changes. + +This sample also highlights a limitation in the library that requires reflection in order to enumerate units for a selected quantity and to get the abbreviation for a unit, since the library does not provide a generic means to retrieve these without referencing types like `Length` and `LengthUnit` directly. There is definitely room for improvement in the library here. + +### Dependencies +http://mahapps.com/ - UI toolkit for WPF \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln b/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln new file mode 100644 index 0000000000..76124d2327 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2020 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitConverter.Wpf", "UnitConverter.Wpf\UnitConverter.Wpf.csproj", "{D04EE35D-496A-4C83-A369-09B9B2BEAEEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D04EE35D-496A-4C83-A369-09B9B2BEAEEC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1A5C77D4-9765-41D3-9C68-AC307DED35E2} + EndGlobalSection +EndGlobal diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln.DotSettings b/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln.DotSettings new file mode 100644 index 0000000000..8939b3c194 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.config b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.config new file mode 100644 index 0000000000..b50c74f35e --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml new file mode 100644 index 0000000000..0601f215a0 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml.cs b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml.cs new file mode 100644 index 0000000000..7244904df2 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/App.xaml.cs @@ -0,0 +1,23 @@ +using System.Windows; + +namespace UnitsNet.Samples.UnitConverter.Wpf +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + protected override void OnStartup(StartupEventArgs e) + { + // BEGIN WORKAROUND + // HACK to fix issue trying to type "1.5" in the Value textbox when bound to a decimal, since "1." is not a valid decimal value + // it will prevent you from typing that. + // We could use Delay=500 in the binding, but it feels weird to only see the updated result value some time after typing + // in a new value. + System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false; + // END WORKAROUND + + base.OnStartup(e); + } + } +} \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/DelegateCommand.cs b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/DelegateCommand.cs new file mode 100644 index 0000000000..b45ce23107 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/DelegateCommand.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows.Input; + +namespace UnitsNet.Samples.UnitConverter.Wpf +{ + /// + /// Simple implementation, that executes a callback upon executing the command, such as + /// when clicking a button. + /// + public sealed class DelegateCommand : ICommand + { + private readonly Action _commandDelegate; + + public DelegateCommand(Action commandDelegate) + { + _commandDelegate = commandDelegate; + } + + public bool CanExecute(object parameter) + { + return true; + } + + public void Execute(object parameter) + { + _commandDelegate.Invoke(); + } + + public event EventHandler CanExecuteChanged; + } +} \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/IMainWindowVm.cs b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/IMainWindowVm.cs new file mode 100644 index 0000000000..c062f6d460 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/IMainWindowVm.cs @@ -0,0 +1,30 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Windows.Input; +using UnitsNet.Samples.UnitConverter.Wpf.Properties; + +namespace UnitsNet.Samples.UnitConverter.Wpf +{ + /// + /// This interface ensures that the view model and the design-time view model are consistent, since the XAML + /// intellisense only knows about the design-time type. + /// + public interface IMainWindowVm : INotifyPropertyChanged + { + ReadOnlyObservableCollection Quantities { get; } + ReadOnlyObservableCollection Units { get; } + QuantityType SelectedQuantity { get; set; } + + [CanBeNull] + UnitListItem SelectedFromUnit { get; set; } + + [CanBeNull] + UnitListItem SelectedToUnit { get; set; } + + string FromHeader { get; } + string ToHeader { get; } + decimal FromValue { get; set; } + decimal ToValue { get; } + ICommand SwapCommand { get; } + } +} \ No newline at end of file diff --git a/Samples/UnitConverter.Wpf/UnitConverter.Wpf/MainWindow.xaml b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/MainWindow.xaml new file mode 100644 index 0000000000..f87c027897 --- /dev/null +++ b/Samples/UnitConverter.Wpf/UnitConverter.Wpf/MainWindow.xaml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +