├── .gitignore ├── DimensionTranslationView_64x.png ├── License.md ├── Readme.md ├── appveyor.yml └── source ├── CleanAll.bat ├── UnitComboLib ├── AssemblyInfo.cs ├── Behaviour │ └── ContextMenuBehaviour.cs ├── Command │ └── RelayCommand.cs ├── Local │ ├── Strings.Designer.cs │ ├── Strings.de-DE.Designer.cs │ ├── Strings.de-DE.resx │ ├── Strings.es-ES.Designer.cs │ ├── Strings.es-ES.resx │ ├── Strings.fr-FR.Designer.cs │ ├── Strings.fr-FR.resx │ ├── Strings.hi-IN.Designer.cs │ ├── Strings.hi-IN.resx │ ├── Strings.id-ID.Designer.cs │ ├── Strings.id-ID.resx │ ├── Strings.it-IT.Designer.cs │ ├── Strings.it-IT.resx │ ├── Strings.ja-JP.Designer.cs │ ├── Strings.ja-JP.resx │ ├── Strings.pt-PT.Designer.cs │ ├── Strings.pt-PT.resx │ ├── Strings.resx │ ├── Strings.ru-RU.Designer.cs │ ├── Strings.ru-RU.resx │ ├── Strings.zh-Hans.Designer.cs │ └── Strings.zh-Hans.resx ├── Models │ ├── ListItem.cs │ └── Unit │ │ ├── Converter.cs │ │ └── Screen │ │ ├── ScreenConverter.cs │ │ ├── ScreenFontPoints.cs │ │ └── ScreenPercent.cs ├── Themes │ ├── DarkBrushs.xaml │ ├── Generic.xaml │ ├── LightBrushs.xaml │ └── ResourceKeys.cs ├── UnitComboLib.csproj ├── UnitComboLib.csproj.user ├── UnitCombobox.xaml ├── UnitCombobox.xaml.cs ├── UnitViewModeService.cs └── ViewModels │ ├── BaseViewModel.cs │ ├── IUnitViewModel.cs │ └── UnitViewModel.cs ├── UnitCombobox.sln └── UnitComboboxDemo ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── UnitComboboxDemo.csproj ├── UnitComboboxDemo.csproj.user └── ViewModels └── AppViewModel.cs /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Visual Studio 2015 cache/options directory 3 | .vs/ 4 | 5 | 00_Release/ 6 | 01_Nuget/ 7 | debug/ 8 | release/ 9 | build/ 10 | bin/ 11 | obj/ 12 | cache/ 13 | log/ 14 | tmp/ 15 | 16 | *~ 17 | *.lock 18 | *.DS_Store 19 | *.swp 20 | *.out 21 | *.sou 22 | *.suo 23 | *.sqlite 24 | -------------------------------------------------------------------------------- /DimensionTranslationView_64x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/DimensionTranslationView_64x.png -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014-2017 Dirk Bahle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/8rmd1b9d35efwunj?svg=true)](https://ci.appveyor.com/project/Dirkster99/unitcombolib) 2 | [![Release](https://img.shields.io/github/release/Dirkster99/UnitComboLib.svg)](https://github.com/Dirkster99/UnitComboLib/releases/latest) 3 | [![NuGet](https://img.shields.io/nuget/dt/Dirkster.UnitComboLib.svg)](http://nuget.org/packages/Dirkster.UnitComboLib) 4 | 5 | ![Net4](https://badgen.net/badge/Framework/.Net 4/blue) ![NetCore3](https://badgen.net/badge/Framework/NetCore 3/blue) 6 | 7 | # Overview 8 | 9 | The WPF UnitComboBox Control implements a combobox that allows the selection of values from different lists. Each list can represent a different unit (eg.: Celsius, Farenheit) and the viewmodel takes care of always converting to one unit (e.g. Celsius). This conversion is independent of what the user selected unit or value actually was. 10 | 11 | This means, the application always sees only one unit and a different value while the user can use whatever unit he prefers to pick the aproppriate value. 12 | 13 | 14 | 15 | 24 | 27 | 28 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 |
29 | 30 | Details are explained in a CodeProject article: 31 | https://www.codeproject.com/Articles/575645/Inheriting-from-a-Look-Less-WPF-Control 32 | 33 | Sample Applications: 34 | - [Edi](https://github.com/Dirkster99/Edi) 35 | - [XmlExplorer](https://github.com/Dirkster99/XmlExplorer) 36 | 37 | ## Theming 38 | 39 | Load *Light* or *Dark* brush resources in you resource dictionary to take advantage of existing definitions. 40 | 41 | ```XAML 42 | 43 | 44 | 45 | ``` 46 | 47 | ```XAML 48 | 49 | 50 | 51 | ``` 52 | 53 | These definitions do not theme all controls used within this library. You should use a standard theming library, such as: 54 | - [MahApps.Metro](https://github.com/MahApps/MahApps.Metro), 55 | - [MLib](https://github.com/Dirkster99/MLib), or 56 | - [MUI](https://github.com/firstfloorsoftware/mui) 57 | 58 | to also theme standard elements, such as, button and textblock etc. 59 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.1.{build} 2 | 3 | configuration: Release 4 | 5 | platform: Any CPU 6 | 7 | image: Visual Studio 2019 Preview 8 | 9 | install: 10 | - cmd: choco install dotnetcore-sdk --pre 11 | 12 | before_build: 13 | - cmd: nuget restore source/UnitCombobox.sln 14 | 15 | build: 16 | 17 | verbosity: minimal 18 | 19 | artifacts: 20 | 21 | - path: source\UnitComboboxDemo\bin\Release 22 | name: UnitComboboxDemo 23 | 24 | - path: source\UnitComboLib\bin\Release 25 | name: UnitComboLib 26 | -------------------------------------------------------------------------------- /source/CleanAll.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | pushd "%~dp0" 3 | ECHO. 4 | ECHO. 5 | ECHO. 6 | ECHO This script deletes all temporary build files in their 7 | ECHO corresponding BIN and OBJ Folder contained in the following projects 8 | ECHO. 9 | ECHO UnitComboboxDemo 10 | ECHO UnitComboLib 11 | ECHO. 12 | REM Ask the user if hes really sure to continue beyond this point XXXXXXXX 13 | set /p choice=Are you sure to continue (Y/N)? 14 | if not '%choice%'=='Y' Goto EndOfBatch 15 | REM Script does not continue unless user types 'Y' in upper case letter 16 | ECHO. 17 | ECHO XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 18 | ECHO. 19 | ECHO XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 20 | ECHO. 21 | ECHO Deleting BIN and OBJ Folders in UnitCombobox 22 | ECHO. 23 | RMDIR /S /Q .\.vs 24 | RMDIR /S /Q .\UnitComboboxDemo\bin 25 | RMDIR /S /Q .\UnitComboboxDemo\obj 26 | ECHO. 27 | ECHO Deleting BIN and OBJ Folders in UnitComboLib 28 | ECHO. 29 | RMDIR /S /Q .\UnitComboLib\bin 30 | RMDIR /S /Q .\UnitComboLib\obj 31 | ECHO. 32 | 33 | PAUSE 34 | 35 | :EndOfBatch 36 | -------------------------------------------------------------------------------- /source/UnitComboLib/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /source/UnitComboLib/Behaviour/ContextMenuBehaviour.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Behaviour 2 | { 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | 6 | /// 7 | /// This class can be used to populate a context-menu 8 | /// when a user clicks on a . 9 | /// 10 | public class ContextMenuBehaviour 11 | { 12 | #region fields 13 | private static readonly DependencyProperty MenuListProperty = 14 | DependencyProperty.RegisterAttached("MenuList", 15 | typeof(ContextMenu), 16 | typeof(ContextMenuBehaviour), 17 | new UIPropertyMetadata(null, ContextMenuBehaviour.OnMenuListChanged)); 18 | #endregion fields 19 | 20 | #region methods 21 | /// 22 | /// Implements the get portion of the dependency property. 23 | /// 24 | /// 25 | /// 26 | public static ContextMenu GetMenuList(DependencyObject obj) 27 | { 28 | return (ContextMenu)obj.GetValue(MenuListProperty); 29 | } 30 | 31 | /// 32 | /// IMplements the set portion of the dependency property. 33 | /// 34 | /// 35 | /// 36 | public static void SetMenuList(DependencyObject obj, ContextMenu value) 37 | { 38 | obj.SetValue(MenuListProperty, value); 39 | } 40 | 41 | /// 42 | /// This method is fired when the dependency property is set or reset. 43 | /// 44 | /// 45 | /// 46 | private static void OnMenuListChanged(DependencyObject d, 47 | DependencyPropertyChangedEventArgs e) 48 | { 49 | var element = d as FrameworkElement; 50 | 51 | if (element != null) 52 | { 53 | element.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(element_MouseLeftButtonUp); 54 | } 55 | else 56 | element.MouseLeftButtonUp -= element_MouseLeftButtonUp; 57 | } 58 | 59 | /// 60 | /// This method is fired when the user clicks on the attached . 61 | /// Its goal is to either open the corresponding via the dependency property 62 | /// or attempt to open the standard context menu of the attached if the dependency property is not set. 63 | /// 64 | /// 65 | /// 66 | private static void element_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) 67 | { 68 | var element = sender as FrameworkElement; 69 | 70 | var target = ContextMenuBehaviour.GetMenuList(element) as ContextMenu; 71 | 72 | if (target != null) 73 | { 74 | // Open context menu defined through dependency property 75 | target.PlacementTarget = (UIElement)sender; 76 | target.IsOpen = true; 77 | } 78 | else 79 | { 80 | if (element != null) 81 | { 82 | // Open context menu on attached framework element 83 | element.ContextMenu.PlacementTarget = (UIElement)sender; 84 | element.ContextMenu.IsOpen = true; 85 | } 86 | } 87 | } 88 | #endregion methods 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /source/UnitComboLib/Command/RelayCommand.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Command 2 | { 3 | using System; 4 | using System.Diagnostics; 5 | using System.Windows.Input; 6 | 7 | /// 8 | /// A command whose sole purpose is to 9 | /// relay its functionality to other 10 | /// objects by invoking delegates. The 11 | /// default return value for the CanExecute 12 | /// method is 'true'. 13 | /// 14 | /// Source: http://www.codeproject.com/Articles/31837/Creating-an-Internationalized-Wizard-in-WPF 15 | /// 16 | public class RelayCommand : ICommand 17 | { 18 | #region Fields 19 | private readonly Action mExecute = null; 20 | private readonly Predicate mCanExecute = null; 21 | #endregion // Fields 22 | 23 | #region Constructors 24 | /// 25 | /// Class constructor 26 | /// 27 | /// 28 | public RelayCommand(Action execute) 29 | : this(execute, null) 30 | { 31 | } 32 | 33 | /// 34 | /// Creates a new command. 35 | /// 36 | /// The execution logic. 37 | /// The execution status logic. 38 | public RelayCommand(Action execute, Predicate canExecute) 39 | { 40 | if (execute == null) 41 | throw new ArgumentNullException("execute"); 42 | 43 | this.mExecute = execute; 44 | this.mCanExecute = canExecute; 45 | } 46 | 47 | #endregion // Constructors 48 | 49 | #region events 50 | /// 51 | /// Eventhandler to re-evaluate whether this command can execute or not 52 | /// 53 | public event EventHandler CanExecuteChanged 54 | { 55 | add 56 | { 57 | if (this.mCanExecute != null) 58 | CommandManager.RequerySuggested += value; 59 | } 60 | 61 | remove 62 | { 63 | if (this.mCanExecute != null) 64 | CommandManager.RequerySuggested -= value; 65 | } 66 | } 67 | #endregion 68 | 69 | #region methods 70 | /// 71 | /// Determine whether this pre-requisites to execute this command are given or not. 72 | /// 73 | /// 74 | /// 75 | [DebuggerStepThrough] 76 | public bool CanExecute(object parameter) 77 | { 78 | return this.mCanExecute == null ? true : this.mCanExecute((T)parameter); 79 | } 80 | 81 | /// 82 | /// Execute the command method managed in this class. 83 | /// 84 | /// 85 | public void Execute(object parameter) 86 | { 87 | this.mExecute((T)parameter); 88 | } 89 | #endregion methods 90 | } 91 | 92 | /// 93 | /// A command whose sole purpose is to 94 | /// relay its functionality to other 95 | /// objects by invoking delegates. The 96 | /// default return value for the CanExecute 97 | /// method is 'true'. 98 | /// 99 | internal class RelayCommand : ICommand 100 | { 101 | #region Fields 102 | private readonly Action mExecute; 103 | private readonly Func mCanExecute; 104 | #endregion Fields 105 | 106 | #region Constructors 107 | 108 | /// 109 | /// Creates a new command that can always execute. 110 | /// 111 | /// The execution logic. 112 | public RelayCommand(Action execute) 113 | : this(execute, null) 114 | { 115 | } 116 | 117 | /// 118 | /// Copy constructor 119 | /// 120 | /// 121 | public RelayCommand(RelayCommand inputRC) 122 | : this(inputRC.mExecute, inputRC.mCanExecute) 123 | { 124 | } 125 | 126 | /// 127 | /// Creates a new command. 128 | /// 129 | /// The execution logic. 130 | /// The execution status logic. 131 | public RelayCommand(Action execute, Func canExecute) 132 | { 133 | if (execute == null) 134 | throw new ArgumentNullException("execute"); 135 | 136 | this.mExecute = execute; 137 | this.mCanExecute = canExecute; 138 | } 139 | 140 | #endregion Constructors 141 | 142 | #region Events 143 | /// 144 | /// Eventhandler to re-evaluate whether this command can execute or not 145 | /// 146 | public event EventHandler CanExecuteChanged 147 | { 148 | add 149 | { 150 | if (this.mCanExecute != null) 151 | CommandManager.RequerySuggested += value; 152 | } 153 | 154 | remove 155 | { 156 | if (this.mCanExecute != null) 157 | CommandManager.RequerySuggested -= value; 158 | } 159 | } 160 | #endregion Events 161 | 162 | #region Methods 163 | /// 164 | /// Execute the attached CanExecute methode delegate (or always return true) 165 | /// to determine whether the command managed in this object can execute or not. 166 | /// 167 | /// 168 | /// 169 | [DebuggerStepThrough] 170 | public bool CanExecute(object parameter) 171 | { 172 | return this.mCanExecute == null ? true : this.mCanExecute(); 173 | } 174 | 175 | /// 176 | /// Return the attached delegate method. 177 | /// 178 | /// 179 | public void Execute(object parameter) 180 | { 181 | this.mExecute(); 182 | } 183 | #endregion Methods 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18034 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace UnitComboLib.Local { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class Strings { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Strings() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UnitComboLib.Local.Strings", typeof(Strings).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Enter a font size in the range of {0} - {1} points.. 65 | /// 66 | public static string Enter_Font_Size_InRange_Message { 67 | get { 68 | return ResourceManager.GetString("Enter_Font_Size_InRange_Message", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Enter a value between {0} - {1} percent or a font size between {2} - {3} points.. 74 | /// 75 | public static string Enter_Percent_Font_Size_InRange_Message { 76 | get { 77 | return ResourceManager.GetString("Enter_Percent_Font_Size_InRange_Message", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Enter a percent value in the range of {0} - {1} percent.. 83 | /// 84 | public static string Enter_Percent_Size_InRange_Message { 85 | get { 86 | return ResourceManager.GetString("Enter_Percent_Size_InRange_Message", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to The string does not contain an integer value.. 92 | /// 93 | public static string Integer_Contain_ErrorMessage { 94 | get { 95 | return ResourceManager.GetString("Integer_Contain_ErrorMessage", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to The string cannot be converted into an integer value.. 101 | /// 102 | public static string Integer_Conversion_ErrorMessage { 103 | get { 104 | return ResourceManager.GetString("Integer_Conversion_ErrorMessage", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to percent. 110 | /// 111 | public static string Percent_String { 112 | get { 113 | return ResourceManager.GetString("Percent_String", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to %. 119 | /// 120 | public static string Percent_String_Short { 121 | get { 122 | return ResourceManager.GetString("Percent_String_Short", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to font size. 128 | /// 129 | public static string Point_String { 130 | get { 131 | return ResourceManager.GetString("Point_String", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to pt. 137 | /// 138 | public static string Point_String_Short { 139 | get { 140 | return ResourceManager.GetString("Point_String_Short", resourceCulture); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.de-DE.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.de-DE.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.de-DE.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Geben Sie einen Schriftgrad im Bereich von {0} - {1} ein. 122 | 123 | 124 | Geben Sie einen prozentualen Wert im Bereich von {0} - {1} oder ein Schriftgrad im Bereich von {2} - {3} ein. 125 | 126 | 127 | Geben Sie einen prozentualen Wert im Bereich von {0} - {1} ein. 128 | 129 | 130 | Die Zeichenfolge beinhaltet keine ganze Zahl. 131 | 132 | 133 | Die Zeichenfolge kann nicht in eine ganze Zahl konvertiert werden. 134 | 135 | 136 | Prozent 137 | describes the unit 'percent' 138 | 139 | 140 | % 141 | describes a short version of the unit 'percent' string 142 | 143 | 144 | Schriftgrad 145 | describes the unit 'point' 146 | 147 | 148 | pt 149 | describes a short version of the unit 'point' string 150 | 151 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.es-ES.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.es-ES.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.es-ES.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Enter a font size in the range of {0} - {1} points. 122 | 123 | 124 | Enter a value between {0} - {1} percent or a font size between {2} - {3} points. 125 | 126 | 127 | Enter a percent value in the range of {0} - {1} percent. 128 | 129 | 130 | The string does not contain an integer value. 131 | 132 | 133 | The string cannot be converted into an integer value. 134 | 135 | 136 | percent 137 | 138 | 139 | % 140 | 141 | 142 | font size 143 | 144 | 145 | pt 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.fr-FR.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.fr-FR.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.fr-FR.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Entrez une taille de police dans la plage de {0} - {1} points. 122 | 123 | 124 | Entrez une valeur entre {0} - {1} pour cent ou une taille de police entre {2} - {3} points. 125 | 126 | 127 | Entrez une valeur en pourcentage de l'ordre de {0} - {1} pour cent. 128 | 129 | 130 | La chaîne ne contient pas une valeur entière. 131 | 132 | 133 | La chaîne ne peut pas être convertie en valeur entière. 134 | 135 | 136 | pour cent 137 | 138 | 139 | % 140 | 141 | 142 | taille de police 143 | 144 | 145 | PT 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.hi-IN.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.hi-IN.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.hi-IN.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | एक फ़ॉन्ट आकार {0} - {1} अंकों की रेंज में दर्ज करें। 122 | 123 | 124 | {0} - {1} प्रतिशत या {2} - {3} अंक के बीच एक फ़ॉन्ट आकार के बीच कोई मान दर्ज करें। 125 | 126 | 127 | {0} - {1} प्रतिशत की सीमा में एक प्रतिशत मान दर्ज करें। 128 | 129 | 130 | स्ट्रिंग एक पूर्णांक मान नहीं है। 131 | 132 | 133 | स्ट्रिंग में एक पूर्णांक मान में कनवर्ट हो नहीं कर सकता। 134 | 135 | 136 | प्रतिशत 137 | 138 | 139 | % 140 | 141 | 142 | फ़ॉन्ट का आकार 143 | 144 | 145 | पीटी 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.id-ID.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.id-ID.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.id-ID.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Masukkan ukuran font dalam kisaran {0} - {1} poin. 122 | 123 | 124 | Masukkan nilai antara {0} - {1} persen atau ukuran font antara (2) - {3} poin. 125 | 126 | 127 | Masukkan nilai persen dalam kisaran {0} - {1} persen. 128 | 129 | 130 | String tidak mengandung nilai integer. 131 | 132 | 133 | String tidak dapat dikonversi menjadi nilai integer. 134 | 135 | 136 | persen 137 | describes the unit 'percent' 138 | 139 | 140 | % 141 | describes a short version of the unit 'percent' string 142 | 143 | 144 | ukuran font 145 | describes the unit 'point' 146 | 147 | 148 | PT 149 | describes a short version of the unit 'point' string 150 | 151 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.it-IT.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.it-IT.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.it-IT.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Immettere una dimensione del carattere dell'intervallo di {0} - {1} punti. 122 | 123 | 124 | Immettere un valore compreso tra {0} - {1} per cento o una dimensione del carattere tra {2} - {3} punti. 125 | 126 | 127 | Immettere un valore percentuale nella gamma di {0} - {1} per cento. 128 | 129 | 130 | La stringa non contiene un valore integer. 131 | 132 | 133 | La stringa non può essere convertita in un valore integer. 134 | 135 | 136 | per cento 137 | 138 | 139 | % 140 | 141 | 142 | dimensione carattere 143 | 144 | 145 | PT 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.ja-JP.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.ja-JP.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.ja-JP.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | {0} - {1} ポイントの範囲でフォント サイズを入力します。 122 | 123 | 124 | {0} - {1} % または {2} - {3} ポイント間のフォント サイズの間の値を入力します。 125 | 126 | 127 | {0} - {1} % の範囲でパーセント値を入力します。 128 | 129 | 130 | 文字列に整数値が含まれていません。 131 | 132 | 133 | 文字列を整数値に変換できません。 134 | 135 | 136 | パーセント 137 | 138 | 139 | % 140 | 141 | 142 | フォント サイズ 143 | 144 | 145 | pt 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.pt-PT.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.pt-PT.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.pt-PT.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Digite um tamanho de fonte na faixa de {0} - {1} pontos. 122 | 123 | 124 | Insira um valor entre {0} - {1} % ou um tamanho de fonte entre {2} - {3} pontos. 125 | 126 | 127 | Digite um valor percentual no intervalo de {0} - {1} %. 128 | 129 | 130 | A seqüência de caracteres não contiver um valor inteiro. 131 | 132 | 133 | A seqüência de caracteres não pode ser convertida em um valor inteiro. 134 | 135 | 136 | por cento 137 | 138 | 139 | % 140 | 141 | 142 | tamanho da fonte 143 | 144 | 145 | pt 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Enter a font size in the range of {0} - {1} points. 122 | 123 | 124 | Enter a value between {0} - {1} percent or a font size between {2} - {3} points. 125 | 126 | 127 | Enter a percent value in the range of {0} - {1} percent. 128 | 129 | 130 | The string does not contain an integer value. 131 | 132 | 133 | The string cannot be converted into an integer value. 134 | 135 | 136 | percent 137 | describes the unit 'percent' 138 | 139 | 140 | % 141 | describes a short version of the unit 'percent' string 142 | 143 | 144 | font size 145 | describes the unit 'point' 146 | 147 | 148 | pt 149 | describes a short version of the unit 'point' string 150 | 151 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.ru-RU.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.ru-RU.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.ru-RU.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Введите размер шрифта в диапазоне от {0} - {1} очков. 122 | 123 | 124 | Введите значение между {0} - {1} процентов или размер шрифта между {2} - {3} очков. 125 | 126 | 127 | Введите процентное значение в диапазоне от {0} - процентов {1}. 128 | 129 | 130 | Строка не содержит целочисленное значение. 131 | 132 | 133 | Строка не может быть преобразована в значение integer. 134 | 135 | 136 | процент 137 | 138 | 139 | % 140 | 141 | 142 | Размер шрифта 143 | 144 | 145 | PT 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.zh-Hans.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dirkster99/UnitComboLib/e237e238239d22fcc0375b0c13ff32c38bd1cf44/source/UnitComboLib/Local/Strings.zh-Hans.Designer.cs -------------------------------------------------------------------------------- /source/UnitComboLib/Local/Strings.zh-Hans.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 输入范围{0}-{1} 点之间的字体大小。 122 | 123 | 124 | 在{0}-{1} %或字体大小 {2}-{3} 点之间输入一个值。 125 | 126 | 127 | 在 {0}-{1} %的范围中输入一个百分比值。 128 | 129 | 130 | 该字符串不包含一个整数值。 131 | 132 | 133 | 该字符串不能转换为一个整数值。 134 | 135 | 136 | % 137 | 138 | 139 | % 140 | 141 | 142 | 字体大小 143 | 144 | 145 | pt 146 | 147 | -------------------------------------------------------------------------------- /source/UnitComboLib/Models/ListItem.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Models 2 | { 3 | using System.Collections.ObjectModel; 4 | using UnitComboLib.Models.Unit; 5 | 6 | /// 7 | /// One item in the list of unit definition items 8 | /// 9 | public class ListItem 10 | { 11 | #region constructor 12 | /// 13 | /// Class constructor. 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | public ListItem(Itemkey key, 20 | string displayNameLong, 21 | string displayNameShort, 22 | ObservableCollection defaultValues) 23 | { 24 | this.Key = key; 25 | this.DisplayNameLong = (displayNameLong == null ? "(null)" : displayNameLong); 26 | this.DisplayNameShort = (displayNameShort == null ? "(null)" : displayNameShort); 27 | 28 | this.DefaultValues = defaultValues; 29 | } 30 | 31 | /// 32 | /// Hidden class constructor. 33 | /// 34 | protected ListItem() 35 | { 36 | } 37 | #endregion constructor 38 | 39 | #region properties 40 | /// 41 | /// Get unit of the values stored in this object (). 42 | /// 43 | public Itemkey Key { get; private set; } 44 | 45 | /// 46 | /// Display a long descriptive string of the unit stored in this object. 47 | /// 48 | public string DisplayNameLong { get; private set; } 49 | 50 | /// 51 | /// Display a short string of the unit stored in this object. 52 | /// 53 | public string DisplayNameShort { get; private set; } 54 | 55 | /// 56 | /// Display a combination of long and short string of the unit stored in this object. 57 | /// 58 | public string DisplayNameLongWithShort 59 | { 60 | get 61 | { 62 | return string.Format("{0} ({1})", this.DisplayNameShort, this.DisplayNameLong); 63 | } 64 | } 65 | 66 | /// 67 | /// Get a list of useful default values for the unit stored in this item. 68 | /// 69 | public ObservableCollection DefaultValues 70 | { 71 | get; 72 | 73 | private set; 74 | } 75 | #endregion properties 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /source/UnitComboLib/Models/Unit/Converter.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Models.Unit 2 | { 3 | /// 4 | /// Enumeration keys for each unit 5 | /// 6 | public enum Itemkey 7 | { 8 | /// 9 | /// Units of computer font screen dimensions 10 | /// 11 | ScreenFontPoints = 5, 12 | 13 | /// 14 | /// A percentage of the with 12 being equivalent to 100%. 15 | /// 16 | ScreenPercent = 6 17 | } 18 | 19 | /// 20 | /// Abstract converter class definition to convert values from one unit to the other. 21 | /// 22 | public abstract class Converter 23 | { 24 | /// 25 | /// Converter method to convert a value from one unit to the other. 26 | /// 27 | /// Unit of 28 | /// Amount of value to convert 29 | /// Expected Unit of value to be converted to. 30 | /// Converted value. 31 | public abstract double Convert(Itemkey inputUnit, double inputValue, Itemkey outputUnit); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /source/UnitComboLib/Models/Unit/Screen/ScreenConverter.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Models.Unit.Screen 2 | { 3 | using System; 4 | 5 | /// 6 | /// Classs to convert font size values into a percentage value and back. 7 | /// 8 | public class ScreenConverter : Converter 9 | { 10 | /// 11 | /// A font size of 12 is equivalent to 100% (percent) display size. 12 | /// 13 | public const double OneHundretPercentFont = 12.0; 14 | 15 | /// 16 | /// This is the standard value to scale against when using percent instead of fontsize. 17 | /// 18 | public const double OneHundretPercent = 100.0; 19 | 20 | /// 21 | /// Convert between different units of screen resolutions. 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public override double Convert(Itemkey inputUnit, double inputValue, Itemkey outputUnit) 28 | { 29 | switch (inputUnit) 30 | { 31 | case Itemkey.ScreenFontPoints: 32 | return ScreenFontPoints.ToUnit(inputValue, outputUnit); 33 | 34 | case Itemkey.ScreenPercent: 35 | return ScreenPercent.ToUnit(inputValue, outputUnit); 36 | 37 | default: 38 | throw new NotImplementedException(outputUnit.ToString()); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /source/UnitComboLib/Models/Unit/Screen/ScreenFontPoints.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Models.Unit.Screen 2 | { 3 | using System; 4 | 5 | /// 6 | /// Class to convert from font sizes to other unit based values. 7 | /// 8 | public class ScreenFontPoints 9 | { 10 | private double mValue = 0; 11 | 12 | #region constructor 13 | /// 14 | /// Class constructor 15 | /// 16 | /// 17 | public ScreenFontPoints(double value) 18 | { 19 | this.mValue = value; 20 | } 21 | 22 | private ScreenFontPoints() 23 | { 24 | } 25 | #endregion constructor 26 | 27 | #region methods 28 | /// 29 | /// Convert a font size to other values. 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static double ToUnit(double inputValue, Itemkey targetUnit) 35 | { 36 | ScreenFontPoints d = new ScreenFontPoints(inputValue); 37 | 38 | return d.ToUnit(targetUnit); 39 | } 40 | 41 | /// 42 | /// Convert a font size to other values. 43 | /// 44 | /// 45 | /// 46 | public double ToUnit(Itemkey targetUnit) 47 | { 48 | switch (targetUnit) 49 | { 50 | case Itemkey.ScreenPercent: 51 | return this.mValue * (100 / ScreenConverter.OneHundretPercentFont); 52 | 53 | case Itemkey.ScreenFontPoints: 54 | return this.mValue; 55 | 56 | default: 57 | throw new NotImplementedException(targetUnit.ToString()); 58 | } 59 | } 60 | #endregion methods 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /source/UnitComboLib/Models/Unit/Screen/ScreenPercent.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Models.Unit.Screen 2 | { 3 | using System; 4 | 5 | /// 6 | /// Class to convert from percentage values into other units. 7 | /// 8 | public class ScreenPercent 9 | { 10 | private double mValue = 0; 11 | 12 | #region constructor 13 | /// 14 | /// Class constructor. 15 | /// 16 | /// 17 | public ScreenPercent(double value) 18 | { 19 | this.mValue = value; 20 | } 21 | 22 | private ScreenPercent() 23 | { 24 | } 25 | #endregion constructor 26 | 27 | #region methods 28 | /// 29 | /// Convert percentage unit based value into another unit based value. 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static double ToUnit(double inputValue, Itemkey targetUnit) 35 | { 36 | ScreenPercent d = new ScreenPercent(inputValue); 37 | 38 | return d.ToUnit(targetUnit); 39 | } 40 | 41 | /// 42 | /// Convert percentage unit based value into another unit based value. 43 | /// 44 | /// 45 | /// 46 | public double ToUnit(Itemkey targetUnit) 47 | { 48 | switch (targetUnit) 49 | { 50 | case Itemkey.ScreenPercent: 51 | return this.mValue; 52 | 53 | case Itemkey.ScreenFontPoints: 54 | return (this.mValue * ScreenConverter.OneHundretPercentFont) / 100.0; 55 | 56 | default: 57 | throw new NotImplementedException(targetUnit.ToString()); 58 | } 59 | } 60 | #endregion methods 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /source/UnitComboLib/Themes/DarkBrushs.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 7 | #FF1888b8 9 | 10 | 13 | 14 | 15 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 45 | 46 | 49 | 50 | 52 | 53 | 55 | 56 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 74 | 75 | 76 | 78 | 79 | -------------------------------------------------------------------------------- /source/UnitComboLib/Themes/Generic.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/UnitComboLib/Themes/LightBrushs.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 7 | #FF1888b8 9 | 10 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 47 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 63 | 65 | 66 | 68 | 69 | 70 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 82 | 83 | 85 | 86 | 87 | 89 | 90 | -------------------------------------------------------------------------------- /source/UnitComboLib/Themes/ResourceKeys.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.Themes 2 | { 3 | using System.Windows; 4 | 5 | /// 6 | /// Resource key management class to keep track of all resources 7 | /// that can be re-styled in applications that make use of the implemented controls. 8 | /// 9 | public static class ResourceKeys 10 | { 11 | #region Accent Keys 12 | /// 13 | /// Accent Color Key - This Color key is used to accent elements in the UI 14 | /// (e.g.: Color of Activated Normal Window Frame, ResizeGrip, Focus or MouseOver input elements) 15 | /// 16 | public static readonly ComponentResourceKey ControlAccentColorKey = new ComponentResourceKey(typeof(ResourceKeys), "ControlAccentColorKey"); 17 | 18 | /// 19 | /// Accent Brush Key - This Brush key is used to accent elements in the UI 20 | /// (e.g.: Color of Activated Normal Window Frame, ResizeGrip, Focus or MouseOver input elements) 21 | /// 22 | public static readonly ComponentResourceKey ControlAccentBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "ControlAccentBrushKey"); 23 | #endregion Accent Keys 24 | 25 | #region Brush Keys 26 | public static readonly ComponentResourceKey NormalBackgroundBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "NormalBackgroundBrushKey"); 27 | public static readonly ComponentResourceKey UnitCmbDarkBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbDarkBrushKey"); 28 | 29 | /// 30 | /// This Brush is used to highlight the ToggleButton on MouseOver 31 | /// 32 | public static readonly ComponentResourceKey UnitCmbHighlighColorBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbHighlighColorBrushKey"); 33 | 34 | public static readonly ComponentResourceKey UnitCmbPressedBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbPressedBrushKey"); 35 | public static readonly ComponentResourceKey UnitCmbDisabledForegroundBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbDisabledForegroundBrushKey"); 36 | public static readonly ComponentResourceKey UnitCmbDisabledBackgroundBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbDisabledBackgroundBrushKey"); 37 | public static readonly ComponentResourceKey UnitCmbWindowBackgroundBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbWindowBackgroundBrushKey"); 38 | 39 | // Border Brushes 40 | public static readonly ComponentResourceKey UnitCmbNormalBorderBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbNormalBorderBrushKey"); 41 | public static readonly ComponentResourceKey UnitCmbDisabledBorderBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbDisabledBorderBrushKey"); 42 | public static readonly ComponentResourceKey UnitCmbSolidBorderBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbSolidBorderBrushKey"); 43 | 44 | // Miscellaneous Brushes 45 | public static readonly ComponentResourceKey UnitCmbGlyphBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "UnitCmbGlyphBrushKey"); 46 | #endregion Brush Keys 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /source/UnitComboLib/UnitComboLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net4;netcoreapp3.0 5 | true 6 | 7 | true 8 | 1.1.0.0 9 | 1.1.0.0 10 | 1.1.0.0 11 | Open Source 12 | UnitComboLib 13 | 2013-2019 14 | The WPF UnitComboBox Control implements a combobox that allows the selection of values from different lists based on different units. 15 | https://github.com/Dirkster99/UnitComboLib 16 | https://github.com/Dirkster99/UnitComboLib 17 | Dirkster.UnitComboLib 18 | https://github.com/Dirkster99/UnitComboLib 19 | MIT 20 | wpf mvvm c# .net metro dark light themed control library unit conversion combobox service API 21 | This control is now supported in NetCore 3 (with Preview 8) and .Net 4. 22 | en 23 | https://raw.githubusercontent.com/Dirkster99/UnitComboLib/master/DimensionTranslationView_64x.png 24 | 25 | 26 | 27 | 28 | 29 | UnitCombobox.xaml 30 | 31 | 32 | 33 | 34 | 35 | Designer 36 | 37 | 38 | Designer 39 | MSBuild:Compile 40 | 41 | 42 | Designer 43 | 44 | 45 | Designer 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /source/UnitComboLib/UnitComboLib.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Designer 7 | 8 | 9 | Designer 10 | 11 | 12 | Designer 13 | 14 | 15 | Designer 16 | 17 | 18 | -------------------------------------------------------------------------------- /source/UnitComboLib/UnitCombobox.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 57 | 58 | 59 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 150 | 151 | 152 | 153 | 154 | 163 | 164 | 165 | 166 | 172 | 173 | 177 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /source/UnitComboLib/UnitCombobox.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib 2 | { 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Controls.Primitives; 6 | 7 | /// 8 | /// This class implements a lookless combobox control with 9 | /// a unit drop-down selection that can be used to pre-select 10 | /// a list of useful combobox entries. 11 | /// 12 | [TemplatePartAttribute(Name = "PART_Popup", Type = typeof(Popup))] 13 | [LocalizabilityAttribute(LocalizationCategory.ComboBox)] 14 | [TemplatePartAttribute(Name = "PART_EditableTextBox", Type = typeof(TextBox))] 15 | [StyleTypedPropertyAttribute(Property = "ItemContainerStyle", StyleTargetType = typeof(ComboBoxItem))] 16 | public class UnitCombobox : ComboBox 17 | { 18 | #region constructor 19 | /// 20 | /// Static class constructor to register look-less class 21 | /// control with the dependency property system. 22 | /// 23 | static UnitCombobox() 24 | { 25 | DefaultStyleKeyProperty.OverrideMetadata(typeof(UnitCombobox), new FrameworkPropertyMetadata(typeof(UnitCombobox))); 26 | } 27 | 28 | /// 29 | /// Standard public class constructor. 30 | /// 31 | public UnitCombobox() : base() 32 | { 33 | } 34 | #endregion constructor 35 | 36 | //// #region Dependency Properties 37 | //// public string MaxStringLen 38 | //// { 39 | //// get { return (string)GetValue(MaxStringLenProperty); } 40 | //// set { SetValue(MaxStringLenProperty, value); } 41 | //// } 42 | //// 43 | //// // Using a DependencyProperty as the backing store for MaxStringLen. This enables animation, styling, binding, etc... 44 | //// public static readonly DependencyProperty MaxStringLenProperty = 45 | //// DependencyProperty.Register("MaxStringLen", 46 | //// typeof(string), typeof(UnitCombobox), new PropertyMetadata(0)); 47 | //// #endregion Dependency Properties 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/UnitComboLib/UnitViewModeService.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib 2 | { 3 | using System.Collections.Generic; 4 | using UnitComboLib.ViewModels; 5 | 6 | public static class UnitViewModeService 7 | { 8 | public static IUnitViewModel CreateInstance( 9 | IList list, 10 | UnitComboLib.Models.Unit.Converter unitConverter, 11 | int defaultIndex = 0, 12 | double defaultValue = 100, 13 | string maxStringLengthValue = "#####") 14 | { 15 | var ret = new UnitViewModel(list, unitConverter, 16 | defaultIndex, defaultValue); 17 | 18 | ret.MaxStringLengthValue = maxStringLengthValue; 19 | 20 | return ret; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /source/UnitComboLib/ViewModels/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.ViewModels 2 | { 3 | using System; 4 | using System.ComponentModel; 5 | using System.Linq.Expressions; 6 | 7 | /// 8 | /// Base class for viewmodel classes being used to communicate 9 | /// between model and view via interface. 10 | /// 11 | public class BaseViewModel : INotifyPropertyChanged 12 | { 13 | /// 14 | /// Event that is fired when a property in the viewmodel changes. 15 | /// 16 | public event PropertyChangedEventHandler PropertyChanged; 17 | 18 | /// 19 | /// Method to invoke when a property has changed its value. Call convention: 20 | /// 21 | /// this.NotifyPropertyChanged(() => this.MyProperty); 22 | /// 23 | /// 24 | /// 25 | public void RaisePropertyChanged(Expression> property) 26 | { 27 | var lambda = (LambdaExpression)property; 28 | MemberExpression memberExpression; 29 | 30 | if (lambda.Body is UnaryExpression) 31 | { 32 | var unaryExpression = (UnaryExpression)lambda.Body; 33 | memberExpression = (MemberExpression)unaryExpression.Operand; 34 | } 35 | else 36 | memberExpression = (MemberExpression)lambda.Body; 37 | 38 | this.OnPropertyChanged(memberExpression.Member.Name); 39 | } 40 | 41 | private void OnPropertyChanged(string propertyName) 42 | { 43 | try 44 | { 45 | if (this.PropertyChanged != null) 46 | this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 47 | } 48 | catch 49 | { 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/UnitComboLib/ViewModels/IUnitViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.ViewModels 2 | { 3 | using System.Collections.ObjectModel; 4 | using System.Windows.Input; 5 | using UnitComboLib.Models; 6 | 7 | public interface IUnitViewModel 8 | { 9 | #region properties 10 | #region IDataErrorInfo Interface 11 | /// 12 | /// Source: http://joshsmithonwpf.wordpress.com/2008/11/14/using-a-viewmodel-to-provide-meaningful-validation-error-messages/ 13 | /// 14 | string Error { get; } 15 | 16 | /// 17 | /// Standard property that is part of the interface. 18 | /// 19 | /// Evaluetes whether StringValue parameter represents a value within the expected range 20 | /// and sets a corresponding errormessage in the ValueTip property if not. 21 | /// 22 | /// Source: http://joshsmithonwpf.wordpress.com/2008/11/14/using-a-viewmodel-to-provide-meaningful-validation-error-messages/ 23 | /// 24 | /// 25 | /// 26 | string this[string propertyName] { get; } 27 | #endregion IDataErrorInfo Interface 28 | 29 | /// 30 | /// Get/sets a string that represents a convinient maximum length in 31 | /// characters to measure the width for the displaying control. 32 | /// 33 | string MaxStringLengthValue { get; set; } 34 | 35 | /// 36 | /// Get the legal maximum value in dependency of the current unit. 37 | /// 38 | double MaxValue { get; } 39 | 40 | /// 41 | /// Get the legal minimum value in dependency of the current unit. 42 | /// 43 | double MinValue { get; } 44 | 45 | /// 46 | /// Currently selected value in screen points. This property is needed because the run-time system 47 | /// cannot work with percent values directly. Therefore, this property always ensures a correct 48 | /// font size no matter what the user selected in percent. 49 | /// 50 | int ScreenPoints { get; set; } 51 | 52 | /// 53 | /// Get/set currently selected unit key, converter, and default value list. 54 | /// 55 | ListItem SelectedItem { get; set; } 56 | 57 | /// 58 | /// Get command to be executed when the user has selected a unit 59 | /// (eg. 'Km' is currently used but user selected 'm' to be used next) 60 | /// 61 | ICommand SetSelectedItemCommand { get; } 62 | 63 | /// 64 | /// String representation of the double value that 65 | /// represents the unit scaled value in this object. 66 | /// 67 | string StringValue { get; set; } 68 | 69 | /// 70 | /// Get list of units, their default value lists, itemkeys etc. 71 | /// 72 | ObservableCollection UnitList { get; } 73 | 74 | /// 75 | /// Get double value represented in unit as indicated by SelectedItem.Key. 76 | /// 77 | double Value { get; set; } 78 | 79 | /// 80 | /// Get a string that indicates the format of the 81 | /// expected input or a an error if the current input is not valid. 82 | /// 83 | string ValueTip { get; } 84 | #endregion properties 85 | } 86 | } -------------------------------------------------------------------------------- /source/UnitComboLib/ViewModels/UnitViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboLib.ViewModels 2 | { 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Windows.Input; 8 | using UnitComboLib.Command; 9 | using UnitComboLib.Local; 10 | using UnitComboLib.Models; 11 | using UnitComboLib.Models.Unit; 12 | 13 | /// 14 | /// Viewmodel class to manage unit conversion based on default values and typed values. 15 | /// 16 | internal class UnitViewModel : BaseViewModel, IDataErrorInfo, IUnitViewModel 17 | { 18 | #region fields 19 | private ListItem _SelectedItem = null; 20 | 21 | private ObservableCollection _UnitList = null; 22 | 23 | private string _ValueTip = string.Empty; 24 | private double _Value = 0; 25 | private string _StrValue = "0.0"; 26 | 27 | private Converter _UnitConverter = null; 28 | 29 | private RelayCommand _SetSelectedItemCommand = null; 30 | 31 | private string _MaxStringLengthValue = "#####"; 32 | 33 | /// 34 | /// Minimum value to be converted for both percentage and pixels 35 | /// 36 | private const double MinFontSizeValue = 2.0; 37 | 38 | /// 39 | /// Maximum value to be converted for both percentage and pixels 40 | /// 41 | private const double MaxFontSizeValue = 399; 42 | 43 | /// 44 | /// Minimum value to be converted for both percentage and pixels 45 | /// 46 | private const double MinPercentageSizeValue = 24; 47 | 48 | /// 49 | /// Maximum value to be converted for both percentage and pixels 50 | /// 51 | private const double MaxPercentageSizeValue = 3325.0; 52 | #endregion fields 53 | 54 | #region constructor 55 | /// 56 | /// Class constructor to construct complete viewmodel object from listed parameters. 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | public UnitViewModel(IList list, 63 | Converter unitConverter, 64 | int defaultIndex = 0, 65 | double defaultValue = 100) 66 | { 67 | this._UnitList = new ObservableCollection(list); 68 | this._SelectedItem = this._UnitList[defaultIndex]; 69 | 70 | this._UnitConverter = unitConverter; 71 | 72 | this._Value = defaultValue; 73 | this._StrValue = string.Format("{0:0}", this._Value); 74 | } 75 | 76 | /// 77 | /// Standard class constructor is hidden in favour of parameterized constructor. 78 | /// 79 | protected UnitViewModel() 80 | { 81 | } 82 | #endregion constructor 83 | 84 | #region properties 85 | /// 86 | /// Currently selected value in screen points. This property is needed because the run-time system 87 | /// cannot work with percent values directly. Therefore, this property always ensures a correct 88 | /// font size no matter what the user selected in percent. 89 | /// 90 | public int ScreenPoints 91 | { 92 | get 93 | { 94 | if (this.SelectedItem != null) 95 | return (int)this._UnitConverter.Convert(this.SelectedItem.Key, this._Value, Itemkey.ScreenFontPoints); 96 | 97 | // Fallback to default if all else fails 98 | return (int)Models.Unit.Screen.ScreenConverter.OneHundretPercentFont; 99 | } 100 | 101 | set 102 | { 103 | if (this.SelectedItem != null) 104 | { 105 | if (this.SelectedItem.Key == Itemkey.ScreenFontPoints) 106 | { 107 | if (value != this.Value) 108 | this.Value = value; 109 | } 110 | else 111 | { 112 | if (value != (int)this._UnitConverter.Convert(this.SelectedItem.Key, this._Value, Itemkey.ScreenFontPoints)) 113 | this.Value = (int)this._UnitConverter.Convert(Itemkey.ScreenFontPoints, value, this.SelectedItem.Key); 114 | } 115 | } 116 | } 117 | } 118 | 119 | /// 120 | /// Get list of units, their default value lists, itemkeys etc. 121 | /// 122 | public ObservableCollection UnitList 123 | { 124 | get 125 | { 126 | return this._UnitList; 127 | } 128 | } 129 | 130 | /// 131 | /// Get/set currently selected unit key, converter, and default value list. 132 | /// 133 | public ListItem SelectedItem 134 | { 135 | get 136 | { 137 | return this._SelectedItem; 138 | } 139 | 140 | set 141 | { 142 | if (this._SelectedItem != value) 143 | { 144 | this._SelectedItem = value; 145 | 146 | this.RaisePropertyChanged(() => this.SelectedItem); 147 | this.RaisePropertyChanged(() => this.ScreenPoints); 148 | this.RaisePropertyChanged(() => this.MinValue); 149 | this.RaisePropertyChanged(() => this.MaxValue); 150 | } 151 | } 152 | } 153 | 154 | #region IDataErrorInfo Interface 155 | /// 156 | /// Source: http://joshsmithonwpf.wordpress.com/2008/11/14/using-a-viewmodel-to-provide-meaningful-validation-error-messages/ 157 | /// 158 | public string Error 159 | { 160 | get 161 | { 162 | return null; 163 | } 164 | } 165 | 166 | /// 167 | /// Standard property that is part of the interface. 168 | /// 169 | /// Evaluetes whether StringValue parameter represents a value within the expected range 170 | /// and sets a corresponding errormessage in the ValueTip property if not. 171 | /// 172 | /// Source: http://joshsmithonwpf.wordpress.com/2008/11/14/using-a-viewmodel-to-provide-meaningful-validation-error-messages/ 173 | /// 174 | /// 175 | /// 176 | public string this[string propertyName] 177 | { 178 | get 179 | { 180 | if (propertyName == "StringValue") 181 | { 182 | if (string.IsNullOrEmpty(this._StrValue)) 183 | return SetToolTip(Strings.Integer_Contain_ErrorMessage); 184 | 185 | double dValue; 186 | if (double.TryParse(this._StrValue, out dValue) == true) 187 | { 188 | string message; 189 | 190 | if (IsDoubleWithinRange(dValue, this.SelectedItem.Key, out message) == true) 191 | { 192 | this.Value = dValue; 193 | return SetToolTip(null); 194 | } 195 | else 196 | return SetToolTip(message); 197 | } 198 | else 199 | return SetToolTip(Strings.Integer_Conversion_ErrorMessage); 200 | } 201 | 202 | return SetToolTip(null); 203 | } 204 | } 205 | #endregion IDataErrorInfo Interface 206 | 207 | /// 208 | /// Get a string that indicates the format of the 209 | /// expected input or a an error if the current input is not valid. 210 | /// 211 | public string ValueTip 212 | { 213 | get 214 | { 215 | return this._ValueTip; 216 | } 217 | 218 | protected set 219 | { 220 | if (this._ValueTip != value) 221 | { 222 | this._ValueTip = value; 223 | this.RaisePropertyChanged(() => this.ValueTip); 224 | } 225 | } 226 | } 227 | 228 | /// 229 | /// Get/sets a string that represents a convinient maximum length in 230 | /// characters to measure the width for the displaying control. 231 | /// 232 | public string MaxStringLengthValue 233 | { 234 | get 235 | { 236 | return _MaxStringLengthValue; 237 | } 238 | 239 | set 240 | { 241 | if (this._MaxStringLengthValue != value) 242 | { 243 | this._MaxStringLengthValue = value; 244 | this.RaisePropertyChanged(() => this.MaxStringLengthValue); 245 | } 246 | } 247 | } 248 | 249 | /// 250 | /// String representation of the double value that 251 | /// represents the unit scaled value in this object. 252 | /// 253 | public string StringValue 254 | { 255 | get 256 | { 257 | return this._StrValue; 258 | } 259 | 260 | set 261 | { 262 | if (this._StrValue != value) 263 | { 264 | this._StrValue = value; 265 | this.RaisePropertyChanged(() => this.StringValue); 266 | } 267 | } 268 | } 269 | 270 | /// 271 | /// Get double value represented in unit as indicated by SelectedItem.Key. 272 | /// 273 | public double Value 274 | { 275 | get 276 | { 277 | return this._Value; 278 | } 279 | 280 | set 281 | { 282 | if (this._Value != value) 283 | { 284 | this._Value = value; 285 | this._StrValue = string.Format("{0:0}", this._Value); 286 | 287 | this.RaisePropertyChanged(() => this.Value); 288 | this.RaisePropertyChanged(() => this.StringValue); 289 | this.RaisePropertyChanged(() => this.ScreenPoints); 290 | } 291 | } 292 | } 293 | 294 | /// 295 | /// Get the legal minimum value in dependency of the current unit. 296 | /// 297 | public double MinValue 298 | { 299 | get 300 | { 301 | return this.GetMinValue(this.SelectedItem.Key); 302 | } 303 | } 304 | 305 | /// 306 | /// Get the legal maximum value in dependency of the current unit. 307 | /// 308 | public double MaxValue 309 | { 310 | get 311 | { 312 | return this.GetMaxValue(this.SelectedItem.Key); 313 | } 314 | } 315 | 316 | /// 317 | /// Get command to be executed when the user has selected a unit 318 | /// (eg. 'Km' is currently used but user selected 'm' to be used next) 319 | /// 320 | public ICommand SetSelectedItemCommand 321 | { 322 | get 323 | { 324 | if (this._SetSelectedItemCommand == null) 325 | this._SetSelectedItemCommand = new RelayCommand(p => this.SetSelectedItemExecuted(p), 326 | p => true); 327 | 328 | return this._SetSelectedItemCommand; 329 | } 330 | } 331 | #endregion properties 332 | 333 | #region methods 334 | /// 335 | /// Convert current double value from current unit to 336 | /// unit as indicated by and 337 | /// set corresponding SelectedItem. 338 | /// 339 | /// New unit to convert double value into and set SelectedItem to. 340 | /// 341 | private object SetSelectedItemExecuted(Itemkey unitKey) 342 | { 343 | // Find the next selected item 344 | ListItem li = this._UnitList.SingleOrDefault(i => i.Key == unitKey); 345 | 346 | // Convert from current item to find the next selected item 347 | if (li != null) 348 | { 349 | double dValue; 350 | if (double.TryParse(this._StrValue, out dValue) == true) 351 | { 352 | double tempValue = this._UnitConverter.Convert(this.SelectedItem.Key, dValue, li.Key); 353 | 354 | if (tempValue < this.GetMinValue(unitKey)) 355 | tempValue = this.GetMinValue(unitKey); 356 | else 357 | if (tempValue > this.GetMaxValue(unitKey)) 358 | tempValue = this.GetMaxValue(unitKey); 359 | 360 | this.Value = tempValue; 361 | this._StrValue = string.Format("{0:0}", this._Value); 362 | 363 | this.SelectedItem = li; 364 | this.ValueTip = this.SetUnitRangeMessage(unitKey); // Set standard tool tip about valid range 365 | } 366 | 367 | this.RaisePropertyChanged(() => this.Value); 368 | this.RaisePropertyChanged(() => this.MinValue); 369 | this.RaisePropertyChanged(() => this.MaxValue); 370 | this.RaisePropertyChanged(() => this.StringValue); 371 | this.RaisePropertyChanged(() => this.SelectedItem); 372 | } 373 | 374 | return null; 375 | } 376 | 377 | /// 378 | /// Check whether the is within the expected 379 | /// range of and output a corresponding 380 | /// error message via parameter if not. 381 | /// 382 | /// 383 | /// 384 | /// 385 | /// False if range is not acceptable, true otherwise 386 | private bool IsDoubleWithinRange(double doubleValue, 387 | Itemkey unitToConvert, 388 | out string message) 389 | { 390 | message = this.SetUnitRangeMessage(unitToConvert); 391 | 392 | switch (unitToConvert) 393 | { 394 | // Implement a minimum value of 2 in any way (no matter what the unit is) 395 | case Itemkey.ScreenFontPoints: 396 | if (doubleValue < MinFontSizeValue) 397 | return false; 398 | else 399 | if (doubleValue > MaxFontSizeValue) 400 | return false; 401 | 402 | return true; 403 | 404 | // Implement a minimum value of 2 in any way (no matter what the unit is) 405 | case Itemkey.ScreenPercent: 406 | if (doubleValue < MinPercentageSizeValue) 407 | return false; 408 | else 409 | if (doubleValue > MaxPercentageSizeValue) 410 | return false; 411 | 412 | return true; 413 | } 414 | 415 | return false; 416 | } 417 | 418 | private string SetUnitRangeMessage(Itemkey unit) 419 | { 420 | switch (unit) 421 | { 422 | // Implement a minimum value of 2 in any way (no matter what the unit is) 423 | case Itemkey.ScreenFontPoints: 424 | return this.FontSizeErrorTip(); 425 | 426 | // Implement a minimum value of 2 in any way (no matter what the unit is) 427 | case Itemkey.ScreenPercent: 428 | return this.PercentSizeErrorTip(); 429 | 430 | default: 431 | throw new System.NotSupportedException(unit.ToString()); 432 | } 433 | } 434 | 435 | /// 436 | /// Generate a standard font message to indicate the expected range value. 437 | /// 438 | /// 439 | private string FontSizeErrorTip() 440 | { 441 | return string.Format(Strings.Enter_Font_Size_InRange_Message, 442 | string.Format("{0:0}", MinFontSizeValue), 443 | string.Format("{0:0}", MaxFontSizeValue)); 444 | } 445 | 446 | /// 447 | /// Generate a standard percent message to indicate the expected range value. 448 | /// 449 | /// 450 | private string PercentSizeErrorTip() 451 | { 452 | return string.Format(Strings.Enter_Percent_Size_InRange_Message, 453 | string.Format("{0:0}", MinPercentageSizeValue), 454 | string.Format("{0:0}", MaxPercentageSizeValue)); 455 | } 456 | 457 | /// 458 | /// Set a tip like string to indicate the expected input format 459 | /// or input errors (if there are any input errors). 460 | /// 461 | /// 462 | /// 463 | private string SetToolTip(string strError) 464 | { 465 | string standardTip = string.Format(Strings.Enter_Percent_Font_Size_InRange_Message, 466 | string.Format("{0:0}", MinPercentageSizeValue), 467 | string.Format("{0:0}", MaxPercentageSizeValue), 468 | string.Format("{0:0}", MinFontSizeValue), 469 | string.Format("{0:0}", MaxFontSizeValue)); 470 | 471 | if (strError == null) 472 | { 473 | if (this.SelectedItem != null) 474 | { 475 | switch (this.SelectedItem.Key) 476 | { 477 | case Itemkey.ScreenFontPoints: 478 | this.ValueTip = this.FontSizeErrorTip(); 479 | break; 480 | 481 | case Itemkey.ScreenPercent: 482 | this.ValueTip = this.PercentSizeErrorTip(); 483 | break; 484 | 485 | default: 486 | this.ValueTip = standardTip; 487 | break; 488 | } 489 | } 490 | else 491 | this.ValueTip = standardTip; 492 | } 493 | else 494 | this.ValueTip = strError; 495 | 496 | return strError; 497 | } 498 | 499 | private double GetMinValue(Itemkey key) 500 | { 501 | if (key == Itemkey.ScreenFontPoints) 502 | return UnitViewModel.MinFontSizeValue; 503 | 504 | return UnitViewModel.MinPercentageSizeValue; 505 | } 506 | 507 | private double GetMaxValue(Itemkey key) 508 | { 509 | if (key == Itemkey.ScreenFontPoints) 510 | return UnitViewModel.MaxFontSizeValue; 511 | 512 | return UnitViewModel.MaxPercentageSizeValue; 513 | } 514 | #endregion methods 515 | } 516 | } 517 | -------------------------------------------------------------------------------- /source/UnitCombobox.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.29209.152 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitComboboxDemo", "UnitComboboxDemo\UnitComboboxDemo.csproj", "{5F5F97C7-F254-4078-A33C-948436946C50}" 6 | EndProject 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitComboLib", "UnitComboLib\UnitComboLib.csproj", "{BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|Any CPU = Release|Any CPU 15 | Release|x64 = Release|x64 16 | Release|x86 = Release|x86 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|x64.ActiveCfg = Debug|Any CPU 22 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|x64.Build.0 = Debug|Any CPU 23 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|x86.ActiveCfg = Debug|Any CPU 24 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Debug|x86.Build.0 = Debug|Any CPU 25 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|x64.ActiveCfg = Release|Any CPU 28 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|x64.Build.0 = Release|Any CPU 29 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|x86.ActiveCfg = Release|Any CPU 30 | {BF6650C8-A4AD-4AFF-95BB-9E64E2F5369A}.Release|x86.Build.0 = Release|Any CPU 31 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|x64.ActiveCfg = Debug|Any CPU 34 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|x64.Build.0 = Debug|Any CPU 35 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|x86.ActiveCfg = Debug|Any CPU 36 | {5F5F97C7-F254-4078-A33C-948436946C50}.Debug|x86.Build.0 = Debug|Any CPU 37 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|x64.ActiveCfg = Release|Any CPU 40 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|x64.Build.0 = Release|Any CPU 41 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|x86.ActiveCfg = Release|Any CPU 42 | {5F5F97C7-F254-4078-A33C-948436946C50}.Release|x86.Build.0 = Release|Any CPU 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | GlobalSection(ExtensibilityGlobals) = postSolution 48 | SolutionGuid = {3F02FC13-2CB6-4457-9E3E-B063B3380808} 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 13 | 14 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace UnitComboboxDemo 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 88 | 89 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboboxDemo 2 | { 3 | using System.Windows; 4 | using UnitComboboxDemo.ViewModels; 5 | 6 | /// 7 | /// Interaction logic for MainWindow.xaml 8 | /// 9 | public partial class MainWindow : Window 10 | { 11 | public MainWindow() 12 | { 13 | this.InitializeComponent(); 14 | 15 | this.DataContext = new AppViewModel(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/UnitComboboxDemo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net4;netcoreapp3.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Code 16 | MainWindow.xaml 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/UnitComboboxDemo.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | Designer 9 | 10 | 11 | 12 | 13 | Designer 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/UnitComboboxDemo/ViewModels/AppViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace UnitComboboxDemo.ViewModels 2 | { 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Diagnostics; 6 | using System.Windows.Input; 7 | using UnitComboLib; 8 | using UnitComboLib.Command; 9 | using UnitComboLib.Models; 10 | using UnitComboLib.Models.Unit; 11 | using UnitComboLib.Models.Unit.Screen; 12 | using UnitComboLib.ViewModels; 13 | 14 | public class AppViewModel : BaseViewModel 15 | { 16 | private ICommand _NavigateWebCommand; 17 | 18 | #region constructor 19 | /// 20 | /// Class constructor 21 | /// 22 | public AppViewModel() 23 | { 24 | this.SizeUnitLabel = UnitViewModeService.CreateInstance( 25 | this.GenerateScreenUnitList(), new ScreenConverter(), 26 | 1, // Default Unit 0 Percent, 1 ScreeFontPoints 27 | 12 // Default Value 28 | ,"###" // Placeholder to measure for maximum expected string len in textbox 29 | ); 30 | } 31 | #endregion constructor 32 | 33 | #region properties 34 | /// 35 | /// Gets the Unit ViewModel that drives 36 | /// the control. 37 | /// 38 | public IUnitViewModel SizeUnitLabel { get; private set; } 39 | 40 | public string CodeProjectUri 41 | { 42 | get 43 | { 44 | return "https://www.codeproject.com/Articles/575645/Inheriting-from-a-Look-Less-WPF-Control"; 45 | } 46 | } 47 | 48 | public string GitHubUri 49 | { 50 | get 51 | { 52 | return "https://github.com/Dirkster99/UnitComboLib"; 53 | } 54 | } 55 | 56 | public string NuGetUri 57 | { 58 | get 59 | { 60 | return "https://preview.nuget.org/packages/Dirkster.UnitComboLib/"; 61 | } 62 | } 63 | 64 | public ICommand NavigateWebCommand 65 | { 66 | get 67 | { 68 | if (_NavigateWebCommand == null) 69 | { 70 | _NavigateWebCommand = new RelayCommand((p) => 71 | { 72 | var param = p as string; 73 | 74 | if (param == null) return; 75 | 76 | Process.Start(new ProcessStartInfo(param)); 77 | }); 78 | } 79 | 80 | return _NavigateWebCommand; 81 | } 82 | } 83 | #endregion properties 84 | 85 | #region methods 86 | private IList GenerateScreenUnitList() 87 | { 88 | IList unitList = new List(); 89 | 90 | var percentDefaults = new ObservableCollection() { "25", "50", "75", "100", "125", "150", "175", "200", "300", "400", "500" }; 91 | var pointsDefaults = new ObservableCollection() { "3", "6", "8", "9", "10", "12", "14", "16", "18", "20", "24", "26", "32", "48", "60" }; 92 | 93 | unitList.Add(new ListItem(Itemkey.ScreenPercent, UnitComboLib.Local.Strings.Percent_String, UnitComboLib.Local.Strings.Percent_String_Short, percentDefaults)); 94 | unitList.Add(new ListItem(Itemkey.ScreenFontPoints, UnitComboLib.Local.Strings.Point_String, UnitComboLib.Local.Strings.Point_String_Short, pointsDefaults)); 95 | 96 | return unitList; 97 | } 98 | #endregion methods 99 | } 100 | } 101 | --------------------------------------------------------------------------------