using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; using System.Windows; using System.ComponentModel; using System.Windows.Markup; using System.Diagnostics; using System.Collections; using System.Collections.Specialized; namespace BuzzGUI.Common { public class CommandBehaviorCollection { #region Behaviors /// /// Behaviors Read-Only Dependency Property /// As you can see the Attached readonly property has a name registered different (BehaviorsInternal) than the property name, this is a tricks os that we can construct the collection as we want /// Read more about this here http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!468.entry /// private static readonly DependencyPropertyKey BehaviorsPropertyKey = DependencyProperty.RegisterAttachedReadOnly("BehaviorsInternal", typeof(BehaviorBindingCollection), typeof(CommandBehaviorCollection), new FrameworkPropertyMetadata((BehaviorBindingCollection)null)); public static readonly DependencyProperty BehaviorsProperty = BehaviorsPropertyKey.DependencyProperty; /// /// Gets the Behaviors property. /// Here we initialze the collection and set the Owner property /// public static BehaviorBindingCollection GetBehaviors(DependencyObject d) { if (d == null) throw new InvalidOperationException("The dependency object trying to attach to is set to null"); BehaviorBindingCollection collection = d.GetValue(CommandBehaviorCollection.BehaviorsProperty) as BehaviorBindingCollection; if (collection == null) { collection = new BehaviorBindingCollection(); collection.Owner = d; SetBehaviors(d, collection); } return collection; } /// /// Provides a secure method for setting the Behaviors property. /// This dependency property indicates .... /// private static void SetBehaviors(DependencyObject d, BehaviorBindingCollection value) { d.SetValue(BehaviorsPropertyKey, value); INotifyCollectionChanged collection = (INotifyCollectionChanged)value; collection.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged); } static void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { BehaviorBindingCollection sourceCollection = (BehaviorBindingCollection)sender; switch (e.Action) { //when an item(s) is added we need to set the Owner property implicitly case NotifyCollectionChangedAction.Add: if (e.NewItems != null) foreach (BehaviorBinding item in e.NewItems) item.Owner = sourceCollection.Owner; break; //when an item(s) is removed we should Dispose the BehaviorBinding case NotifyCollectionChangedAction.Remove: if (e.OldItems != null) foreach (BehaviorBinding item in e.OldItems) item.Behavior.Dispose(); break; //here we have to set the owner property to the new item and unregister the old item case NotifyCollectionChangedAction.Replace: if (e.NewItems != null) foreach (BehaviorBinding item in e.NewItems) item.Owner = sourceCollection.Owner; if (e.OldItems != null) foreach (BehaviorBinding item in e.OldItems) item.Behavior.Dispose(); break; //when an item(s) is removed we should Dispose the BehaviorBinding case NotifyCollectionChangedAction.Reset: if (e.OldItems != null) foreach (BehaviorBinding item in e.OldItems) item.Behavior.Dispose(); break; case NotifyCollectionChangedAction.Move: default: break; } } #endregion } /// /// Collection to store the list of behaviors. This is done so that you can intiniate it from XAML /// This inherits from freezable so that it gets inheritance context for DataBinding to work /// public class BehaviorBindingCollection : FreezableCollection { /// /// Gets or sets the Owner of the binding /// public DependencyObject Owner { get; set; } } }