PageRenderTime 26ms CodeModel.GetById 15ms app.highlight 8ms 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//===================================================================================
 17using System.Collections.Generic;
 18using System.Windows;
 19using System.Windows.Data;
 20
 21namespace Microsoft.Practices.Prism.Interactivity
 22{
 23    /// <summary>
 24    /// The delegate to invoke when the value monitored by the <see cref="BindingListener"/> changes.
 25    /// </summary>
 26    /// <param name="sender">The sender of the event.</param>
 27    /// <param name="e">The binding changed information.</param>
 28    [System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Design", "CA1003:UseGenericEventHandlerInstances")]
 29    public delegate void ChangedHandler(object sender, BindingChangedEventArgs e);
 30
 31    /// <summary>
 32    /// Attaches a binding lister to a <see cref="FrameworkElement"/> to enable the use
 33    /// of binding expressions from items that don't support <see cref="Binding"/> expressions (e.g. Expression Blend
 34    /// Silverlight 3 Behaviors).
 35    /// </summary>
 36    /// <remarks>
 37    /// This was taken, with permission, from Peter Blois (http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html)
 38    /// </remarks>
 39    public class BindingListener
 40    {
 41        private static readonly List<DependencyPropertyListener> freeListeners = new List<DependencyPropertyListener>();
 42
 43        private readonly ChangedHandler changedHandler;
 44        private Binding binding;
 45        private DependencyPropertyListener listener;
 46        private FrameworkElement target;
 47        private object value;
 48
 49        ///<summary>
 50        /// Intantiates a new instance of the BindingListener.
 51        ///</summary>
 52        ///<param name="changedHandler"></param>
 53        public BindingListener(ChangedHandler changedHandler)
 54        {
 55            this.changedHandler = changedHandler;
 56        }
 57
 58        /// <summary>
 59        /// Gets or sets the <see cref="Binding"/> to when attaching the dependency property.
 60        /// </summary>
 61        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "value")]
 62        public Binding Binding
 63        {
 64            get { return this.binding; }
 65            set
 66            {
 67                this.binding = value;
 68                this.Attach();
 69            }
 70        }
 71
 72        /// <summary>
 73        /// Gets or sets the framework element to attach the listener to.
 74        /// </summary>
 75        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "value")]
 76        public FrameworkElement Element
 77        {
 78            get { return this.target; }
 79            set
 80            {
 81                this.target = value;
 82                this.Attach();
 83            }
 84        }
 85
 86        /// <summary>
 87        /// The value of the underlying monitored object.
 88        /// </summary>
 89        public object Value
 90        {
 91            get { return this.value; }
 92        }
 93
 94        private void Attach()
 95        {
 96            this.Detach();
 97
 98            if (this.target != null && this.binding != null)
 99            {
100                this.listener = this.GetListener();
101                this.listener.Attach(this.target, this.binding);
102            }
103        }
104
105        private void Detach()
106        {
107            if (this.listener != null)
108            {
109                this.ReturnListener();
110            }
111        }
112
113        private DependencyPropertyListener GetListener()
114        {
115            DependencyPropertyListener dependencyPropertyListener;
116
117            if (freeListeners.Count != 0)
118            {
119                dependencyPropertyListener = freeListeners[freeListeners.Count - 1];
120                freeListeners.RemoveAt(freeListeners.Count - 1);
121
122                return dependencyPropertyListener;
123            }
124            else
125            {
126                dependencyPropertyListener = new DependencyPropertyListener();
127            }
128
129            dependencyPropertyListener.Changed += this.HandleValueChanged;
130
131            return dependencyPropertyListener;
132        }
133
134        private void HandleValueChanged(object sender, BindingChangedEventArgs e)
135        {
136            this.value = e.EventArgs.NewValue;
137
138            this.changedHandler(this, e);
139        }
140
141        private void ReturnListener()
142        {
143            this.listener.Changed -= this.HandleValueChanged;
144
145            freeListeners.Add(this.listener);
146
147            this.listener = null;
148        }
149    }
150}