PriorityBindingEntry.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using Avalonia.Data;
  5. namespace Avalonia
  6. {
  7. /// <summary>
  8. /// A registered binding in a <see cref="PriorityValue"/>.
  9. /// </summary>
  10. internal class PriorityBindingEntry : IDisposable
  11. {
  12. private PriorityLevel _owner;
  13. private IDisposable _subscription;
  14. /// <summary>
  15. /// Initializes a new instance of the <see cref="PriorityBindingEntry"/> class.
  16. /// </summary>
  17. /// <param name="owner">The owner.</param>
  18. /// <param name="index">
  19. /// The binding index. Later bindings should have higher indexes.
  20. /// </param>
  21. public PriorityBindingEntry(PriorityLevel owner, int index)
  22. {
  23. _owner = owner;
  24. Index = index;
  25. }
  26. /// <summary>
  27. /// Gets the observable associated with the entry.
  28. /// </summary>
  29. public IObservable<object> Observable { get; private set; }
  30. /// <summary>
  31. /// Gets a description of the binding.
  32. /// </summary>
  33. public string Description
  34. {
  35. get;
  36. private set;
  37. }
  38. /// <summary>
  39. /// Gets the binding entry index. Later bindings will have higher indexes.
  40. /// </summary>
  41. public int Index
  42. {
  43. get;
  44. }
  45. /// <summary>
  46. /// The current value of the binding.
  47. /// </summary>
  48. public object Value
  49. {
  50. get;
  51. private set;
  52. }
  53. /// <summary>
  54. /// Starts listening to the binding.
  55. /// </summary>
  56. /// <param name="binding">The binding.</param>
  57. public void Start(IObservable<object> binding)
  58. {
  59. Contract.Requires<ArgumentNullException>(binding != null);
  60. if (_subscription != null)
  61. {
  62. throw new Exception("PriorityValue.Entry.Start() called more than once.");
  63. }
  64. Observable = binding;
  65. Value = AvaloniaProperty.UnsetValue;
  66. if (binding is IDescription)
  67. {
  68. Description = ((IDescription)binding).Description;
  69. }
  70. _subscription = binding.Subscribe(ValueChanged, Completed);
  71. }
  72. /// <summary>
  73. /// Ends the binding subscription.
  74. /// </summary>
  75. public void Dispose()
  76. {
  77. _subscription?.Dispose();
  78. }
  79. private void ValueChanged(object value)
  80. {
  81. _owner.Owner.Owner?.VerifyAccess();
  82. var notification = value as BindingNotification;
  83. if (notification != null)
  84. {
  85. if (notification.HasValue || notification.ErrorType == BindingErrorType.Error)
  86. {
  87. Value = notification.Value;
  88. _owner.Changed(this);
  89. }
  90. if (notification.ErrorType != BindingErrorType.None)
  91. {
  92. _owner.Error(this, notification);
  93. }
  94. }
  95. else
  96. {
  97. Value = value;
  98. _owner.Changed(this);
  99. }
  100. }
  101. private void Completed()
  102. {
  103. _owner.Completed(this);
  104. }
  105. }
  106. }