PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/V4/PrismLibrary/Phone/Prism.Interactivity/BindingListener.cs

#
C# | 150 lines | 88 code | 20 blank | 42 comment | 8 complexity | 51ed9924f586dde9662fad138b0fce46 MD5 | raw file
  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4. //===================================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===================================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===================================================================================
  17. using System.Collections.Generic;
  18. using System.Windows;
  19. using System.Windows.Data;
  20. namespace Microsoft.Practices.Prism.Interactivity
  21. {
  22. /// <summary>
  23. /// The delegate to invoke when the value monitored by the <see cref="BindingListener"/> changes.
  24. /// </summary>
  25. /// <param name="sender">The sender of the event.</param>
  26. /// <param name="e">The binding changed information.</param>
  27. [System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Design", "CA1003:UseGenericEventHandlerInstances")]
  28. public delegate void ChangedHandler(object sender, BindingChangedEventArgs e);
  29. /// <summary>
  30. /// Attaches a binding lister to a <see cref="FrameworkElement"/> to enable the use
  31. /// of binding expressions from items that don't support <see cref="Binding"/> expressions (e.g. Expression Blend
  32. /// Silverlight 3 Behaviors).
  33. /// </summary>
  34. /// <remarks>
  35. /// This was taken, with permission, from Peter Blois (http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html)
  36. /// </remarks>
  37. public class BindingListener
  38. {
  39. private static readonly List<DependencyPropertyListener> freeListeners = new List<DependencyPropertyListener>();
  40. private readonly ChangedHandler changedHandler;
  41. private Binding binding;
  42. private DependencyPropertyListener listener;
  43. private FrameworkElement target;
  44. private object value;
  45. ///<summary>
  46. /// Intantiates a new instance of the BindingListener.
  47. ///</summary>
  48. ///<param name="changedHandler"></param>
  49. public BindingListener(ChangedHandler changedHandler)
  50. {
  51. this.changedHandler = changedHandler;
  52. }
  53. /// <summary>
  54. /// Gets or sets the <see cref="Binding"/> to when attaching the dependency property.
  55. /// </summary>
  56. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "value")]
  57. public Binding Binding
  58. {
  59. get { return this.binding; }
  60. set
  61. {
  62. this.binding = value;
  63. this.Attach();
  64. }
  65. }
  66. /// <summary>
  67. /// Gets or sets the framework element to attach the listener to.
  68. /// </summary>
  69. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "value")]
  70. public FrameworkElement Element
  71. {
  72. get { return this.target; }
  73. set
  74. {
  75. this.target = value;
  76. this.Attach();
  77. }
  78. }
  79. /// <summary>
  80. /// The value of the underlying monitored object.
  81. /// </summary>
  82. public object Value
  83. {
  84. get { return this.value; }
  85. }
  86. private void Attach()
  87. {
  88. this.Detach();
  89. if (this.target != null && this.binding != null)
  90. {
  91. this.listener = this.GetListener();
  92. this.listener.Attach(this.target, this.binding);
  93. }
  94. }
  95. private void Detach()
  96. {
  97. if (this.listener != null)
  98. {
  99. this.ReturnListener();
  100. }
  101. }
  102. private DependencyPropertyListener GetListener()
  103. {
  104. DependencyPropertyListener dependencyPropertyListener;
  105. if (freeListeners.Count != 0)
  106. {
  107. dependencyPropertyListener = freeListeners[freeListeners.Count - 1];
  108. freeListeners.RemoveAt(freeListeners.Count - 1);
  109. return dependencyPropertyListener;
  110. }
  111. else
  112. {
  113. dependencyPropertyListener = new DependencyPropertyListener();
  114. }
  115. dependencyPropertyListener.Changed += this.HandleValueChanged;
  116. return dependencyPropertyListener;
  117. }
  118. private void HandleValueChanged(object sender, BindingChangedEventArgs e)
  119. {
  120. this.value = e.EventArgs.NewValue;
  121. this.changedHandler(this, e);
  122. }
  123. private void ReturnListener()
  124. {
  125. this.listener.Changed -= this.HandleValueChanged;
  126. freeListeners.Add(this.listener);
  127. this.listener = null;
  128. }
  129. }
  130. }