LogicalNotNode.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System;
  2. using System.Globalization;
  3. namespace Avalonia.Data.Core
  4. {
  5. public class LogicalNotNode : ExpressionNode, ITransformNode
  6. {
  7. public override string Description => "!";
  8. protected override void NextValueChanged(object value)
  9. {
  10. base.NextValueChanged(Negate(value));
  11. }
  12. private static object Negate(object value)
  13. {
  14. var notification = value as BindingNotification;
  15. var v = BindingNotification.ExtractValue(value);
  16. BindingNotification GenerateError(Exception e)
  17. {
  18. notification ??= new BindingNotification(AvaloniaProperty.UnsetValue);
  19. notification.AddError(e, BindingErrorType.Error);
  20. notification.ClearValue();
  21. return notification;
  22. }
  23. if (v != AvaloniaProperty.UnsetValue)
  24. {
  25. var s = v as string;
  26. if (s != null)
  27. {
  28. bool result;
  29. if (bool.TryParse(s, out result))
  30. {
  31. return !result;
  32. }
  33. else
  34. {
  35. return GenerateError(new InvalidCastException($"Unable to convert '{s}' to bool."));
  36. }
  37. }
  38. else
  39. {
  40. try
  41. {
  42. var boolean = Convert.ToBoolean(v, CultureInfo.InvariantCulture);
  43. if (notification is object)
  44. {
  45. notification.SetValue(!boolean);
  46. return notification;
  47. }
  48. else
  49. {
  50. return !boolean;
  51. }
  52. }
  53. catch (InvalidCastException)
  54. {
  55. // The error message here is "Unable to cast object of type 'System.Object'
  56. // to type 'System.IConvertible'" which is kinda useless so provide our own.
  57. return GenerateError(new InvalidCastException($"Unable to convert '{v}' to bool."));
  58. }
  59. catch (Exception e)
  60. {
  61. return GenerateError(e);
  62. }
  63. }
  64. }
  65. return notification ?? AvaloniaProperty.UnsetValue;
  66. }
  67. public object Transform(object value)
  68. {
  69. var originalType = value.GetType();
  70. var negated = Negate(value);
  71. if (negated is BindingNotification)
  72. {
  73. return negated;
  74. }
  75. return Convert.ChangeType(negated, originalType);
  76. }
  77. }
  78. }