PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/source/library/Interlace/Binding/DelegateBinder.cs

https://bitbucket.org/VahidN/interlace
C# | 183 lines | 127 code | 31 blank | 25 comment | 12 complexity | 06ca84e1ecc2d014980e854ebc62c444 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.ComponentModel;
  30. using System.Reflection;
  31. using System.Text;
  32. using Interlace.Binding.Views;
  33. #endregion
  34. namespace Interlace.Binding
  35. {
  36. public delegate void DelegateBinderDelegate<TSender, TProperty>(TSender sender, TProperty value);
  37. public delegate void DelegateBinderDelegate<TProperty>(TProperty value);
  38. public delegate void DelegateBinderDelegate();
  39. public class DelegateBinder
  40. {
  41. object _boundTo = null;
  42. Type _boundToType = null;
  43. Dictionary<string, List<InternalDelegateBinderDelegate>> _bindings;
  44. public delegate void InternalDelegateBinderDelegate(object sender, object value);
  45. public DelegateBinder()
  46. {
  47. _bindings = new Dictionary<string, List<InternalDelegateBinderDelegate>>();
  48. }
  49. public DelegateBinder(object boundTo)
  50. : this()
  51. {
  52. BoundTo = boundTo;
  53. }
  54. public DelegateBinder(Interlace.Binding.Binder boundToBinder, string propertyName)
  55. : this()
  56. {
  57. boundToBinder.AddBinding(propertyName, new PropertyView(this, "BoundTo", null));
  58. }
  59. public object BoundTo
  60. {
  61. get { return _boundTo; }
  62. set
  63. {
  64. if (_boundTo == value) return;
  65. if (_boundTo != null) DisconnectEvents();
  66. _boundTo = value;
  67. if (_boundTo != null)
  68. {
  69. _boundToType = _boundTo.GetType();
  70. ConnectEvents();
  71. FireAllBindings();
  72. }
  73. else
  74. {
  75. _boundToType = null;
  76. }
  77. }
  78. }
  79. void ConnectEvents()
  80. {
  81. if (_boundTo is INotifyPropertyChanged)
  82. {
  83. INotifyPropertyChanged notifier = _boundTo as INotifyPropertyChanged;
  84. notifier.PropertyChanged += new PropertyChangedEventHandler(PropertyChangedEventHandler);
  85. }
  86. else
  87. {
  88. throw new InvalidOperationException(
  89. "The DelegateBinder can only be bound to objects implementing INotifyPropertyChanged.");
  90. }
  91. }
  92. void DisconnectEvents()
  93. {
  94. if (_boundTo is INotifyPropertyChanged)
  95. {
  96. INotifyPropertyChanged notifier = _boundTo as INotifyPropertyChanged;
  97. notifier.PropertyChanged -= new PropertyChangedEventHandler(PropertyChangedEventHandler);
  98. }
  99. else
  100. {
  101. throw new InvalidOperationException();
  102. }
  103. }
  104. void FireAllBindings()
  105. {
  106. foreach (string propertyName in _bindings.Keys)
  107. {
  108. FireBinding(propertyName);
  109. }
  110. }
  111. void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e)
  112. {
  113. FireBinding(e.PropertyName);
  114. }
  115. void FireBinding(string propertyName)
  116. {
  117. if (_bindings.ContainsKey(propertyName))
  118. {
  119. object value = null;
  120. PropertyInfo propertyInfo = _boundToType.GetProperty(propertyName);
  121. if (propertyInfo != null) value = propertyInfo.GetValue(_boundTo, null);
  122. foreach (InternalDelegateBinderDelegate binderDelegate in _bindings[propertyName])
  123. {
  124. binderDelegate(_boundTo, value);
  125. }
  126. }
  127. }
  128. public void Bind<TSender, TProperty>(string propertyName, DelegateBinderDelegate<TSender, TProperty> bindTo)
  129. {
  130. Bind(propertyName,
  131. (InternalDelegateBinderDelegate)delegate(object sender, object value) { bindTo((TSender)sender, (TProperty)value); });
  132. }
  133. public void Bind<TProperty>(string propertyName, DelegateBinderDelegate<TProperty> bindTo)
  134. {
  135. Bind(propertyName,
  136. (InternalDelegateBinderDelegate)delegate(object sender, object value) { bindTo((TProperty)value); });
  137. }
  138. public void Bind(string propertyName, DelegateBinderDelegate bindTo)
  139. {
  140. Bind(propertyName,
  141. (InternalDelegateBinderDelegate)delegate(object sender, object value) { bindTo(); });
  142. }
  143. void Bind(string propertyName, InternalDelegateBinderDelegate bindTo)
  144. {
  145. if (!_bindings.ContainsKey(propertyName))
  146. {
  147. _bindings[propertyName] = new List<InternalDelegateBinderDelegate>();
  148. }
  149. _bindings[propertyName].Add(bindTo);
  150. }
  151. }
  152. }