/MahApps.Metro/Converters/MathConverter.cs

https://github.com/beckzhu/SimpleRemote
C# | 263 lines | 192 code | 37 blank | 34 comment | 16 complexity | 7b29173740afca1084515e6984e8057e MD5 | raw file
  1. using System;
  2. using System.Diagnostics;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Windows.Data;
  6. using System.Windows;
  7. using System.Windows.Markup;
  8. namespace MahApps.Metro.Converters
  9. {
  10. /// <summary>
  11. /// The math operations which can be used at the <see cref="MathConverter"/>
  12. /// </summary>
  13. public enum MathOperation
  14. {
  15. Add,
  16. Subtract,
  17. Multiply,
  18. Divide
  19. }
  20. /// <summary>
  21. /// MathConverter provides a value converter which can be used for math operations.
  22. /// It can be used for normal binding or multi binding as well.
  23. /// If it is used for normal binding the given parameter will be used as operands with the selected operation.
  24. /// If it is used for multi binding then the first and second binding will be used as operands with the selected operation.
  25. /// This class cannot be inherited.
  26. /// </summary>
  27. public sealed class MathConverter : IValueConverter, IMultiValueConverter
  28. {
  29. public MathOperation Operation { get; set; }
  30. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  31. {
  32. return DoConvert(value, parameter, this.Operation);
  33. }
  34. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  35. {
  36. if (values == null || values.Length < 2)
  37. {
  38. return Binding.DoNothing;
  39. }
  40. return DoConvert(values[0], values[1], this.Operation);
  41. }
  42. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  43. {
  44. return Binding.DoNothing;
  45. }
  46. public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  47. {
  48. return targetTypes.Select(t => Binding.DoNothing).ToArray();
  49. }
  50. private static object DoConvert(object firstValue, object secondValue, MathOperation operation)
  51. {
  52. if (firstValue == null
  53. || secondValue == null
  54. || firstValue == DependencyProperty.UnsetValue
  55. || secondValue == DependencyProperty.UnsetValue
  56. || firstValue == DBNull.Value
  57. || secondValue == DBNull.Value)
  58. {
  59. return Binding.DoNothing;
  60. }
  61. try
  62. {
  63. var value1 = (firstValue as double?).GetValueOrDefault(System.Convert.ToDouble(firstValue, CultureInfo.InvariantCulture));
  64. var value2 = (secondValue as double?).GetValueOrDefault(System.Convert.ToDouble(secondValue, CultureInfo.InvariantCulture));
  65. switch (operation)
  66. {
  67. case MathOperation.Add:
  68. return value1 + value2;
  69. case MathOperation.Divide:
  70. return value1 / value2;
  71. case MathOperation.Multiply:
  72. return value1 * value2;
  73. case MathOperation.Subtract:
  74. return value1 - value2;
  75. default:
  76. return Binding.DoNothing;
  77. }
  78. }
  79. catch (Exception e)
  80. {
  81. Trace.TraceError($"Error while converting: value1={firstValue} value2={secondValue} operation={operation} exception: {e}");
  82. return Binding.DoNothing;
  83. }
  84. }
  85. }
  86. /// <summary>
  87. /// MathAddConverter provides a multi value converter as a MarkupExtension which can be used for math operations.
  88. /// This class cannot be inherited.
  89. /// </summary>
  90. [MarkupExtensionReturnType(typeof(MathAddConverter))]
  91. public sealed class MathAddConverter : MarkupMultiConverter
  92. {
  93. private static MathAddConverter _instance;
  94. private readonly MathConverter theMathConverter = new MathConverter() { Operation = MathOperation.Add };
  95. // Explicit static constructor to tell C# compiler
  96. // not to mark type as beforefieldinit
  97. static MathAddConverter()
  98. {
  99. }
  100. public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  101. {
  102. return this.theMathConverter.Convert(values, targetType, parameter, culture);
  103. }
  104. public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  105. {
  106. return this.theMathConverter.Convert(value, targetType, parameter, culture);
  107. }
  108. public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  109. {
  110. return this.theMathConverter.ConvertBack(value, targetTypes, parameter, culture);
  111. }
  112. public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  113. {
  114. return this.theMathConverter.ConvertBack(value, targetType, parameter, culture);
  115. }
  116. public override object ProvideValue(IServiceProvider serviceProvider)
  117. {
  118. return _instance ?? (_instance = new MathAddConverter());
  119. }
  120. }
  121. /// <summary>
  122. /// MathSubtractConverter provides a multi value converter as a MarkupExtension which can be used for math operations.
  123. /// This class cannot be inherited.
  124. /// </summary>
  125. [MarkupExtensionReturnType(typeof(MathSubtractConverter))]
  126. public sealed class MathSubtractConverter : MarkupMultiConverter
  127. {
  128. private static MathSubtractConverter _instance;
  129. private readonly MathConverter theMathConverter = new MathConverter() { Operation = MathOperation.Subtract };
  130. // Explicit static constructor to tell C# compiler
  131. // not to mark type as beforefieldinit
  132. static MathSubtractConverter()
  133. {
  134. }
  135. public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  136. {
  137. return this.theMathConverter.Convert(values, targetType, parameter, culture);
  138. }
  139. public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  140. {
  141. return this.theMathConverter.Convert(value, targetType, parameter, culture);
  142. }
  143. public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  144. {
  145. return this.theMathConverter.ConvertBack(value, targetTypes, parameter, culture);
  146. }
  147. public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  148. {
  149. return this.theMathConverter.ConvertBack(value, targetType, parameter, culture);
  150. }
  151. public override object ProvideValue(IServiceProvider serviceProvider)
  152. {
  153. return _instance ?? (_instance = new MathSubtractConverter());
  154. }
  155. }
  156. /// <summary>
  157. /// MathMultiplyConverter provides a multi value converter as a MarkupExtension which can be used for math operations.
  158. /// This class cannot be inherited.
  159. /// </summary>
  160. [MarkupExtensionReturnType(typeof(MathMultiplyConverter))]
  161. public sealed class MathMultiplyConverter : MarkupMultiConverter
  162. {
  163. private static MathMultiplyConverter _instance;
  164. private readonly MathConverter theMathConverter = new MathConverter() { Operation = MathOperation.Multiply };
  165. // Explicit static constructor to tell C# compiler
  166. // not to mark type as beforefieldinit
  167. static MathMultiplyConverter()
  168. {
  169. }
  170. public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  171. {
  172. return this.theMathConverter.Convert(values, targetType, parameter, culture);
  173. }
  174. public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  175. {
  176. return this.theMathConverter.Convert(value, targetType, parameter, culture);
  177. }
  178. public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  179. {
  180. return this.theMathConverter.ConvertBack(value, targetTypes, parameter, culture);
  181. }
  182. public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  183. {
  184. return this.theMathConverter.ConvertBack(value, targetType, parameter, culture);
  185. }
  186. public override object ProvideValue(IServiceProvider serviceProvider)
  187. {
  188. return _instance ?? (_instance = new MathMultiplyConverter());
  189. }
  190. }
  191. /// <summary>
  192. /// MathDivideConverter provides a multi value converter as a MarkupExtension which can be used for math operations.
  193. /// This class cannot be inherited.
  194. /// </summary>
  195. [MarkupExtensionReturnType(typeof(MathDivideConverter))]
  196. public sealed class MathDivideConverter : MarkupMultiConverter
  197. {
  198. private static MathDivideConverter _instance;
  199. private readonly MathConverter theMathConverter = new MathConverter() { Operation = MathOperation.Divide };
  200. // Explicit static constructor to tell C# compiler
  201. // not to mark type as beforefieldinit
  202. static MathDivideConverter()
  203. {
  204. }
  205. public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  206. {
  207. return this.theMathConverter.Convert(values, targetType, parameter, culture);
  208. }
  209. public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  210. {
  211. return this.theMathConverter.Convert(value, targetType, parameter, culture);
  212. }
  213. public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  214. {
  215. return this.theMathConverter.ConvertBack(value, targetTypes, parameter, culture);
  216. }
  217. public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  218. {
  219. return this.theMathConverter.ConvertBack(value, targetType, parameter, culture);
  220. }
  221. public override object ProvideValue(IServiceProvider serviceProvider)
  222. {
  223. return _instance ?? (_instance = new MathDivideConverter());
  224. }
  225. }
  226. }