1#if !XAMARIN && !WINDOWS_UWP
10using System.Collections.Specialized;
12using System.Windows.Controls;
13using System.Windows.Data;
14using System.Windows.Media;
15using System.ComponentModel;
16using System.Reflection;
28 private object _dataObject;
54 this.DataContextChanged +=
new DependencyPropertyChangedEventHandler(Panel_DataContextChanged);
55 this.Loaded +=
new RoutedEventHandler(Panel_Loaded);
58 private void Panel_Loaded(
object sender, RoutedEventArgs e)
60 UpdateDataObject(
null, _dataObject);
67 private void Panel_DataContextChanged(
object sender, DependencyPropertyChangedEventArgs e)
69 UpdateDataObject(e.OldValue, e.NewValue);
72 private object GetDataObject(
object dataContext)
74 object result = dataContext;
75 DataSourceProvider provider = dataContext as DataSourceProvider;
78 result = provider.Data;
82 var icv = dataContext as ICollectionView;
84 result = icv.CurrentItem;
93 private void DataProvider_DataChanged(
object sender, EventArgs e)
95 UpdateDataObject(_dataObject, ((DataSourceProvider)sender).Data);
98 private void UpdateDataObject(
object oldObject,
object newObject)
100 if (!ReferenceEquals(oldObject, newObject))
102 if (oldObject !=
null)
103 UnHookDataContextEvents(oldObject);
106 _dataObject = GetDataObject(newObject);
108 if (newObject !=
null)
109 HookDataContextEvents(newObject);
115#region Hook/unhook events
117 private void UnHookDataContextEvents(
object oldValue)
120 object oldContext =
null;
122 DataSourceProvider provider = oldValue as DataSourceProvider;
123 if (provider ==
null)
125 oldContext = oldValue;
129 provider.DataChanged -=
new EventHandler(DataProvider_DataChanged);
130 oldContext = provider.Data;
133 UnHookPropertyChanged(oldContext as INotifyPropertyChanged);
134 INotifyCollectionChanged observable = oldContext as INotifyCollectionChanged;
135 if (observable !=
null)
136 UnHookObservableListChanged(observable);
138 UnHookBindingListChanged(oldContext as IBindingList);
141 private void HookDataContextEvents(
object newValue)
144 object newContext =
null;
146 DataSourceProvider provider = newValue as DataSourceProvider;
147 if (provider ==
null)
149 newContext = newValue;
153 provider.DataChanged += DataProvider_DataChanged;
154 newContext = provider.Data;
157 HookPropertyChanged(newContext as INotifyPropertyChanged);
158 INotifyCollectionChanged observable = newContext as INotifyCollectionChanged;
159 if (observable !=
null)
160 HookObservableListChanged(observable);
162 HookBindingListChanged(newContext as IBindingList);
165 private void UnHookPropertyChanged(INotifyPropertyChanged oldContext)
167 if (oldContext !=
null)
168 oldContext.PropertyChanged -= DataObject_PropertyChanged;
171 private void HookPropertyChanged(INotifyPropertyChanged newContext)
173 if (newContext !=
null)
174 newContext.PropertyChanged += DataObject_PropertyChanged;
179 if (oldContext !=
null)
180 oldContext.ChildChanged -= DataObject_ChildChanged;
185 if (newContext !=
null)
186 newContext.ChildChanged += DataObject_ChildChanged;
189 private void UnHookBindingListChanged(IBindingList oldContext)
191 if (oldContext !=
null)
192 oldContext.ListChanged -= DataObject_ListChanged;
195 private void HookBindingListChanged(IBindingList newContext)
197 if (newContext !=
null)
198 newContext.ListChanged += DataObject_ListChanged;
201 private void UnHookObservableListChanged(INotifyCollectionChanged oldContext)
203 if (oldContext !=
null)
204 oldContext.CollectionChanged -= DataObject_CollectionChanged;
207 private void HookObservableListChanged(INotifyCollectionChanged newContext)
209 if (newContext !=
null)
210 newContext.CollectionChanged += DataObject_CollectionChanged;
217 private void DataObject_PropertyChanged(
object sender, PropertyChangedEventArgs e)
227 private void DataObject_ListChanged(
object sender, ListChangedEventArgs e)
232 private void DataObject_CollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
239#region Virtual methods
284#region FindingBindings
297 private void FindBindings(Visual visual)
299 for (
int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
301 Visual childVisual = (Visual)VisualTreeHelper.GetChild(visual, i);
302 MemberInfo[] sharedMembers = childVisual.GetType().GetMembers(
303 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
304 foreach (MemberInfo member
in sharedMembers)
306 DependencyProperty prop =
null;
307 if (member.MemberType == MemberTypes.Field)
308 prop = ((FieldInfo)member).GetValue(childVisual) as DependencyProperty;
309 else if (member.MemberType == MemberTypes.Property)
310 prop = ((System.Reflection.PropertyInfo)member).GetValue(childVisual,
null) as DependencyProperty;
314 Binding bnd = BindingOperations.GetBinding(childVisual, prop);
315 if (bnd !=
null && bnd.RelativeSource ==
null && bnd.Path !=
null &&
string.IsNullOrEmpty(bnd.ElementName))
319 FindBindings(childVisual);
331 protected virtual void FoundBinding(Binding bnd, FrameworkElement control, DependencyProperty prop)
Contains event data about the changed child object.
Base class for creating WPF panel controls that react when the DataContext, data object and data prop...
virtual void DataObjectChanged()
This method is called when the data object to which the control is bound has changed.
DataDecoratorBase()
Creates an instance of the object.
virtual void DataBindingListChanged(ListChangedEventArgs e)
This method is called if the data object is an IBindingList, and the ListChanged event was raised by ...
object DataObject
Gets a reference to the current data object.
virtual void DataObservableCollectionChanged(NotifyCollectionChangedEventArgs e)
This method is called if the data object is an INotifyCollectionChanged, and the CollectionChanged ev...
virtual void DataPropertyChanged(PropertyChangedEventArgs e)
This method is called when a property of the data object to which the control is bound has changed.
virtual void FoundBinding(Binding bnd, FrameworkElement control, DependencyProperty prop)
Called by FindChildBindings each time an object binding is found.
void FindChildBindings()
Scans all child controls of this panel for object bindings, and calls FoundBinding for each binding f...
Implemented by classes that notify when a child object has changed.