1: /// <summary>
2: /// ItemsSourceChanged Behavior uses an Attached Dependency Property
3: /// to add and raise a rotued event whenever an ItemsControl's ItemsSource property
4: /// changes. Also looks for INotifyCollectionChanged on the ItemsSource and raises the
5: /// event on every collection changed event
6: /// </summary>
7: public static class ItemsSourceChangedBehavior
8: {
9: #region ItemsSourceChanged Property
10:
11: /// <summary>
12: /// ItemsSourceChanged Attached Dependency Property with Callback method
13: /// </summary>
14: public static readonly DependencyProperty ItemsSourceChangedProperty =
15: DependencyProperty.RegisterAttached("ItemsSourceChanged",
16: typeof(bool), typeof(ItemsSourceChangedBehavior),
17: new FrameworkPropertyMetadata(false, OnItemsSourceChanged));
18:
19: /// <summary>
20: /// Static Get method allowing easy Xaml usage and to simplify the
21: /// GetValue process
22: /// </summary>
23: /// <param name="obj">The dependency obj.</param>
24: /// <returns>True or False</returns>
25: public static bool GetItemsSourceChanged(DependencyObject obj)
26: {
27: return (bool)obj.GetValue(ItemsSourceChangedProperty);
28: }
29:
30: /// <summary>
31: /// Static Set method allowing easy Xaml usage and to simplify the
32: /// Setvalue process
33: /// </summary>
34: /// <param name="obj">The obj.</param>
35: /// <param name="value">if set to <c>true</c> [value].</param>
36: public static void SetItemsSourceChanged(DependencyObject obj, bool value)
37: {
38: obj.SetValue(ItemsSourceChangedProperty, value);
39: }
40:
41: /// <summary>
42: /// Dependency Property Changed Call Back method. This will be called anytime
43: /// the ItemsSourceChangedProperty value changes on a Dependency Object
44: /// </summary>
45: /// <param name="obj">The obj.</param>
46: /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
47: private static void OnItemsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
48: {
49: ItemsControl itemsControl = obj as ItemsControl;
50:
51: if (itemsControl == null)
52: return;
53:
54: bool oldValue = (bool)e.OldValue;
55: bool newValue = (bool)e.NewValue;
56:
57: if (!oldValue && newValue) // If changed from false to true
58: {
59: // Create a binding to the ItemsSourceProperty on the ItemsControl
60: Binding b = new Binding
61: {
62: Source = itemsControl,
63: Path = new PropertyPath(ItemsControl.ItemsSourceProperty)
64: };
65:
66: // Since the ItemsSourceListenerProperty is now bound to the
67: // ItemsSourceProperty on the ItemsControl, whenever the
68: // ItemsSourceProperty changes the ItemsSourceListenerProperty
69: // callback method will execute
70: itemsControl.SetBinding(ItemsSourceListenerProperty, b);
71: }
72: else if (oldValue && !newValue) // If changed from true to false
73: {
74: // Clear Binding on the ItemsSourceListenerProperty
75: BindingOperations.ClearBinding(itemsControl, ItemsSourceListenerProperty);
76: }
77: }
78:
79: #endregion
80:
81: #region Items Source Listener Property
82:
83: /// <summary>
84: /// The ItemsSourceListener Attached Dependency Property is a private property
85: /// the ItemsSourceChangedBehavior will use silently to bind to the ItemsControl
86: /// ItemsSourceProperty.
87: /// Once bound, the callback method will execute anytime the ItemsSource property changes
88: /// </summary>
89: private static readonly DependencyProperty ItemsSourceListenerProperty =
90: DependencyProperty.RegisterAttached("ItemsSourceListener",
91: typeof(object), typeof(ItemsSourceChangedBehavior),
92: new FrameworkPropertyMetadata(null, OnItemsSourceListenerChanged));
93:
94:
95: /// <summary>
96: /// Dependency Property Changed Call Back method. This will be called anytime
97: /// the ItemsSourceListenerProperty value changes on a Dependency Object
98: /// </summary>
99: /// <param name="obj">The obj.</param>
100: /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
101: private static void OnItemsSourceListenerChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
102: {
103: ItemsControl itemsControl = obj as ItemsControl;
104:
105: if (itemsControl == null)
106: return;
107:
108: INotifyCollectionChanged collection = e.NewValue as INotifyCollectionChanged;
109:
110: if (collection != null)
111: {
112: collection.CollectionChanged += delegate
113: {
114: itemsControl.RaiseEvent(new RoutedEventArgs(ItemsSourceChangedEvent));
115: };
116:
117: }
118:
119: if (GetItemsSourceChanged(itemsControl))
120: itemsControl.RaiseEvent(new RoutedEventArgs(ItemsSourceChangedEvent));
121: }
122:
123: #endregion
124:
125: #region Items Source Changed Event
126:
127: /// <summary>
128: /// Routed Event to raise whenever the ItemsSource changes on an ItemsControl
129: /// </summary>
130: public static readonly RoutedEvent ItemsSourceChangedEvent =
131: EventManager.RegisterRoutedEvent("ItemsSourceChanged",
132: RoutingStrategy.Bubble,
133: typeof(RoutedEventHandler),
134: typeof(ItemsControl));
135:
136: #endregion
137: }