CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
DataDecoratorBase.cs
Go to the documentation of this file.
1#if !XAMARIN && !WINDOWS_UWP
2//-----------------------------------------------------------------------
3// <copyright file="DataDecoratorBase.cs" company="Marimer LLC">
4// Copyright (c) Marimer LLC. All rights reserved.
5// Website: https://cslanet.com
6// </copyright>
7// <summary>Base class for creating WPF panel</summary>
8//-----------------------------------------------------------------------
9using System;
10using System.Collections.Specialized;
11using System.Windows;
12using System.Windows.Controls;
13using System.Windows.Data;
14using System.Windows.Media;
15using System.ComponentModel;
16using System.Reflection;
17
18namespace Csla.Xaml
19{
26 public class DataDecoratorBase : Decorator
27 {
28 private object _dataObject;
29
41 protected object DataObject
42 {
43 get
44 {
45 return _dataObject;
46 }
47 }
48
53 {
54 this.DataContextChanged += new DependencyPropertyChangedEventHandler(Panel_DataContextChanged);
55 this.Loaded += new RoutedEventHandler(Panel_Loaded);
56 }
57
58 private void Panel_Loaded(object sender, RoutedEventArgs e)
59 {
60 UpdateDataObject(null, _dataObject);
61 }
62
67 private void Panel_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
68 {
69 UpdateDataObject(e.OldValue, e.NewValue);
70 }
71
72 private object GetDataObject(object dataContext)
73 {
74 object result = dataContext;
75 DataSourceProvider provider = dataContext as DataSourceProvider;
76 if (provider != null)
77 {
78 result = provider.Data;
79 }
80 else
81 {
82 var icv = dataContext as ICollectionView;
83 if (icv != null)
84 result = icv.CurrentItem;
85 }
86 return result;
87 }
88
93 private void DataProvider_DataChanged(object sender, EventArgs e)
94 {
95 UpdateDataObject(_dataObject, ((DataSourceProvider)sender).Data);
96 }
97
98 private void UpdateDataObject(object oldObject, object newObject)
99 {
100 if (!ReferenceEquals(oldObject, newObject))
101 {
102 if (oldObject != null)
103 UnHookDataContextEvents(oldObject);
104
105 // store a ref to the data object
106 _dataObject = GetDataObject(newObject);
107
108 if (newObject != null)
109 HookDataContextEvents(newObject);
110
112 }
113 }
114
115#region Hook/unhook events
116
117 private void UnHookDataContextEvents(object oldValue)
118 {
119 // unhook any old event handling
120 object oldContext = null;
121
122 DataSourceProvider provider = oldValue as DataSourceProvider;
123 if (provider == null)
124 {
125 oldContext = oldValue;
126 }
127 else
128 {
129 provider.DataChanged -= new EventHandler(DataProvider_DataChanged);
130 oldContext = provider.Data;
131 }
132 UnHookChildChanged(oldContext as Csla.Core.INotifyChildChanged);
133 UnHookPropertyChanged(oldContext as INotifyPropertyChanged);
134 INotifyCollectionChanged observable = oldContext as INotifyCollectionChanged;
135 if (observable != null)
136 UnHookObservableListChanged(observable);
137 else
138 UnHookBindingListChanged(oldContext as IBindingList);
139 }
140
141 private void HookDataContextEvents(object newValue)
142 {
143 // hook any new event
144 object newContext = null;
145
146 DataSourceProvider provider = newValue as DataSourceProvider;
147 if (provider == null)
148 {
149 newContext = newValue;
150 }
151 else
152 {
153 provider.DataChanged += DataProvider_DataChanged;
154 newContext = provider.Data;
155 }
156 HookChildChanged(newContext as Csla.Core.INotifyChildChanged);
157 HookPropertyChanged(newContext as INotifyPropertyChanged);
158 INotifyCollectionChanged observable = newContext as INotifyCollectionChanged;
159 if (observable != null)
160 HookObservableListChanged(observable);
161 else
162 HookBindingListChanged(newContext as IBindingList);
163 }
164
165 private void UnHookPropertyChanged(INotifyPropertyChanged oldContext)
166 {
167 if (oldContext != null)
168 oldContext.PropertyChanged -= DataObject_PropertyChanged;
169 }
170
171 private void HookPropertyChanged(INotifyPropertyChanged newContext)
172 {
173 if (newContext != null)
174 newContext.PropertyChanged += DataObject_PropertyChanged;
175 }
176
177 private void UnHookChildChanged(Csla.Core.INotifyChildChanged oldContext)
178 {
179 if (oldContext != null)
180 oldContext.ChildChanged -= DataObject_ChildChanged;
181 }
182
183 private void HookChildChanged(Csla.Core.INotifyChildChanged newContext)
184 {
185 if (newContext != null)
186 newContext.ChildChanged += DataObject_ChildChanged;
187 }
188
189 private void UnHookBindingListChanged(IBindingList oldContext)
190 {
191 if (oldContext != null)
192 oldContext.ListChanged -= DataObject_ListChanged;
193 }
194
195 private void HookBindingListChanged(IBindingList newContext)
196 {
197 if (newContext != null)
198 newContext.ListChanged += DataObject_ListChanged;
199 }
200
201 private void UnHookObservableListChanged(INotifyCollectionChanged oldContext)
202 {
203 if (oldContext != null)
204 oldContext.CollectionChanged -= DataObject_CollectionChanged;
205 }
206
207 private void HookObservableListChanged(INotifyCollectionChanged newContext)
208 {
209 if (newContext != null)
210 newContext.CollectionChanged += DataObject_CollectionChanged;
211 }
212
213#endregion
214
215#region Handle events
216
217 private void DataObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
218 {
220 }
221
222 private void DataObject_ChildChanged(object sender, Csla.Core.ChildChangedEventArgs e)
223 {
224 DataPropertyChanged(e.PropertyChangedArgs);
225 }
226
227 private void DataObject_ListChanged(object sender, ListChangedEventArgs e)
228 {
230 }
231
232 private void DataObject_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
233 {
235 }
236
237#endregion
238
239#region Virtual methods
240
246 protected virtual void DataPropertyChanged(PropertyChangedEventArgs e)
247 {
248 // may be overridden by subclass
249 }
250
257 protected virtual void DataBindingListChanged(ListChangedEventArgs e)
258 {
259 // may be overridden by subclass
260 }
261
268 protected virtual void DataObservableCollectionChanged(NotifyCollectionChangedEventArgs e)
269 {
270 }
271
277 protected virtual void DataObjectChanged()
278 {
279 // may be overridden by subclass
280 }
281
282#endregion
283
284#region FindingBindings
285
292 protected void FindChildBindings()
293 {
294 FindBindings(this);
295 }
296
297 private void FindBindings(Visual visual)
298 {
299 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
300 {
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)
305 {
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;
311
312 if (prop != null)
313 {
314 Binding bnd = BindingOperations.GetBinding(childVisual, prop);
315 if (bnd != null && bnd.RelativeSource == null && bnd.Path != null && string.IsNullOrEmpty(bnd.ElementName))
316 FoundBinding(bnd, (FrameworkElement)childVisual, prop);
317 }
318 }
319 FindBindings(childVisual);
320 }
321 }
322
331 protected virtual void FoundBinding(Binding bnd, FrameworkElement control, DependencyProperty prop)
332 {
333 }
334
335#endregion
336 }
337}
338#endif
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.