Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DependencyObjectExtensions.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Windows;
7 using System.Reflection;
8 using System.Windows.Media;
9 
10 namespace SiliconStudio.Presentation.Extensions
11 {
12  public static class DependencyObjectExtensions
13  {
14  /// <summary>
15  /// Retrieves the public static DependencyProperties.
16  /// </summary>
17  /// <param name="source">DependencyObject that contains the DependencyProperties to be retrieved.</param>
18  /// <param name="includingParentProperties">Indicates whether the DependencyProperties declared in the parent classes have to be retrieved too.</param>
19  /// <returns>Returns an array of DependencyProperty owned by the DependencyObject.</returns>
20  public static DependencyProperty[] GetDependencyProperties(this DependencyObject source, bool includingParentProperties = false)
21  {
22  if (source == null)
23  throw new ArgumentNullException("source");
24 
25  // there is probably a better way using TypeDescriptor
26 
27  Type dependencyPropertyType = typeof(DependencyProperty);
28 
29  BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
30  if (includingParentProperties)
31  flags |= BindingFlags.FlattenHierarchy;
32 
33  return source.DependencyObjectType.SystemType.GetFields(flags)
34  .Where(fi => fi.MemberType == MemberTypes.Field && fi.FieldType == dependencyPropertyType)
35  .Select(fi => (DependencyProperty)fi.GetValue(source))
36  .OrderBy(fi => fi.Name)
37  .ToArray();
38  }
39 
40  /// <summary>
41  /// Sets the value of a DependencyProperty on a DependencyObject and all its logical children.
42  /// </summary>
43  /// <param name="source">Root DependencyObject of which to set the DependencyProperty value.</param>
44  /// <param name="property">DependencyProperty to set.</param>
45  /// <param name="value">Value to set.</param>
46  public static void DeepSetValue(this DependencyObject source, DependencyProperty property, object value)
47  {
48  if (source == null)
49  throw new ArgumentNullException("source");
50  if (property == null)
51  throw new ArgumentNullException("property");
52 
53  source.SetValue(property, value);
54  foreach (object child in LogicalTreeHelper.GetChildren(source as dynamic))
55  {
56  var depChild = child as DependencyObject;
57  if (depChild != null)
58  depChild.DeepSetValue(property, value);
59  }
60  }
61 
62  /// <summary>
63  /// Find the root parent that match the given type, along the visual tree.
64  /// </summary>
65  /// <typeparam name="T">Type of parent to find.</typeparam>
66  /// <param name="source">Base node from where to start looking for parent.</param>
67  /// <returns>Returns the retrieved parent, or null otherwise.</returns>
68  public static Visual FindVisualRoot(this DependencyObject source)
69  {
70  if (source == null)
71  throw new ArgumentNullException("source");
72 
73  Visual root = null;
74  while (source != null)
75  {
76  root = source as Visual;
77  source = VisualTreeHelper.GetParent(source);
78  }
79  return root;
80  }
81 
82  /// <summary>
83  /// Find the first parent that match the given type, along the visual tree.
84  /// </summary>
85  /// <typeparam name="T">Type of parent to find.</typeparam>
86  /// <param name="source">Base node from where to start looking for parent.</param>
87  /// <returns>Returns the retrieved parent, or null otherwise.</returns>
88  public static T FindVisualParentOfType<T>(this DependencyObject source) where T : DependencyObject
89  {
90  if (source == null)
91  throw new ArgumentNullException("source");
92 
93  return FindParentOfType<T>(source, VisualTreeHelper.GetParent);
94  }
95 
96  /// <summary>
97  /// Find the first child that match the given type, along the visual tree.
98  /// </summary>
99  /// <typeparam name="T">Type of child to find.</typeparam>
100  /// <param name="source">Base node from where to start looking for child.</param>
101  /// <returns>Returns the retrieved child, or null otherwise.</returns>
102  public static T FindVisualChildOfType<T>(this DependencyObject source) where T : DependencyObject
103  {
104  if (source == null)
105  throw new ArgumentNullException("source");
106 
107  return FindChildOfType<T>(source, VisualTreeHelper.GetChildrenCount, VisualTreeHelper.GetChild);
108  }
109 
110  /// <summary>
111  /// Find all the children that match the given type, along the visual tree.
112  /// </summary>
113  /// <typeparam name="T">Type of child to find.</typeparam>
114  /// <param name="source">Base node from where to start looking for children.</param>
115  /// <returns>Returns the retrieved children, or empty otherwise.</returns>
116  public static IEnumerable<T> FindVisualChildrenOfType<T>(this DependencyObject source) where T : DependencyObject
117  {
118  if (source == null)
119  throw new ArgumentNullException("source");
120 
121  return FindChildrenOfType<T>(source, VisualTreeHelper.GetChildrenCount, VisualTreeHelper.GetChild);
122  }
123 
124  /// <summary>
125  /// Gets the first visual child of the given object.
126  /// </summary>
127  /// <param name="source">The object in which to look for a child.</param>
128  /// <returns>The child if the given object has children, <c>null</c> otherwise.</returns>
130  {
131  int childrenCount = VisualTreeHelper.GetChildrenCount(source);
132  return childrenCount > 0 ? VisualTreeHelper.GetChild(source, 0) : null;
133  }
134 
135  /// <summary>
136  /// Find the first parent that match the given type, along the logical tree.
137  /// </summary>
138  /// <typeparam name="T">Type of parent to find.</typeparam>
139  /// <param name="source">Base node from where to start looking for parent.</param>
140  /// <returns>Returns the retrieved parent, or null otherwise.</returns>
141  public static T FindLogicalParentOfType<T>(this DependencyObject source) where T : DependencyObject
142  {
143  if (source == null)
144  throw new ArgumentNullException("source");
145 
146  return FindParentOfType<T>(source, LogicalTreeHelper.GetParent);
147  }
148 
149  /// <summary>
150  /// Finds the first child that match the given type, along the logical tree.
151  /// Warning: this function is inefficient, use it for debug but not production.
152  /// </summary>
153  /// <typeparam name="T">Type of child to find.</typeparam>
154  /// <param name="source">Base node from where to start looking for child.</param>
155  /// <returns>Returns the retrieved child, or null otherwise.</returns>
156  public static T FindLogicalChildOfType<T>(this DependencyObject source) where T : DependencyObject
157  {
158  if (source == null)
159  throw new ArgumentNullException("source");
160 
161  return FindChildOfType<T>(source,
162  d => LogicalTreeHelper.GetChildren(d).Cast<DependencyObject>().Count(),
163  (d, i) => LogicalTreeHelper.GetChildren(d).Cast<DependencyObject>().ElementAt(i));
164  }
165 
166  /// <summary>
167  /// Finds all the children that match the given type, along the logical tree.
168  /// Warning: this function is inefficient, use it for debug but not production.
169  /// </summary>
170  /// <typeparam name="T">Type of child to find.</typeparam>
171  /// <param name="source">Base node from where to start looking for children.</param>
172  /// <returns>Returns the retrieved children, or empty otherwise.</returns>
173  public static IEnumerable<T> FindLogicalChildrenOfType<T>(this DependencyObject source) where T : DependencyObject
174  {
175  if (source == null)
176  throw new ArgumentNullException("source");
177 
178  return FindChildrenOfType<T>(source,
179  d => LogicalTreeHelper.GetChildren(d).Cast<DependencyObject>().Count(),
180  (d, i) => LogicalTreeHelper.GetChildren(d).Cast<DependencyObject>().ElementAt(i));
181  }
182 
183 
184  #region Helper methods
185 
186  /// <summary>
187  /// Find the first parent that match the given type.
188  /// </summary>
189  /// <typeparam name="T">Type of parent to find.</typeparam>
190  /// <param name="source">Base node from where to start looking for parent.</param>
191  /// <param name="getParentFunc">Function that provide the parent element.</param>
192  /// <returns>Returns the retrieved parent, or null otherwise.</returns>
193  private static T FindParentOfType<T>(DependencyObject source, Func<DependencyObject, DependencyObject> getParentFunc) where T : DependencyObject
194  {
195  if (source == null)
196  throw new ArgumentNullException("source");
197  if (getParentFunc == null)
198  throw new ArgumentNullException("getParentFunc");
199 
200  // try to get visual parent
201  var parent = getParentFunc(source);
202 
203  if (parent != null)
204  {
205  if (parent is T)
206  {
207  // parent is of requested type, returned casted
208  return parent as T;
209  }
210 
211  // there is a parent but not of request type, let's keep traversing the tree up
212  return FindParentOfType<T>(parent, getParentFunc);
213  }
214 
215  // failed to find visual parent
216  return null;
217  }
218 
219  /// <summary>
220  /// Find the first child that match the given type.
221  /// </summary>
222  /// <typeparam name="T">Type of child to find.</typeparam>
223  /// <param name="source">Base node from where to start looking for child.</param>
224  /// <param name="getChildrenCountFunc">Function that provide the number of children in the current element.</param>
225  /// <param name="getChildFunc">Function that provide a given child element by its index.</param>
226  /// <returns>Returns the retrieved child, or null otherwise.</returns>
227  private static T FindChildOfType<T>(DependencyObject source, Func<DependencyObject, int> getChildrenCountFunc, Func<DependencyObject, int, DependencyObject> getChildFunc) where T : DependencyObject
228  {
229  if (source == null)
230  throw new ArgumentNullException("source");
231  if (getChildrenCountFunc == null)
232  throw new ArgumentNullException("getChildrenCountFunc");
233  if (getChildFunc == null)
234  throw new ArgumentNullException("getChildFunc");
235 
236  var childCount = getChildrenCountFunc(source);
237  for (var i = 0; i < childCount; i++)
238  {
239  var child = getChildFunc(source, i);
240  if (child != null)
241  {
242  if (child is T)
243  return child as T;
244  child = FindChildOfType<T>(child, getChildrenCountFunc, getChildFunc);
245  if (child != null)
246  return (T)child;
247  }
248  }
249  return null;
250  }
251 
252  /// <summary>
253  /// Find all the children that match the given type.
254  /// </summary>
255  /// <typeparam name="T">Type of child to find.</typeparam>
256  /// <param name="source">Base node from where to start looking for children.</param>
257  /// <param name="getChildrenCountFunc">Function that provide the number of children in the current element.</param>
258  /// <param name="getChildFunc">Function that provide a given child element by its index.</param>
259  /// <returns>Returns the retrieved children, empty otherwise.</returns>
260  private static IEnumerable<T> FindChildrenOfType<T>(DependencyObject source, Func<DependencyObject, int> getChildrenCountFunc, Func<DependencyObject, int, DependencyObject> getChildFunc) where T : DependencyObject
261  {
262  if (source == null)
263  throw new ArgumentNullException("source");
264  if (getChildrenCountFunc == null)
265  throw new ArgumentNullException("getChildrenCountFunc");
266  if (getChildFunc == null)
267  throw new ArgumentNullException("getChildFunc");
268 
269  var childCount = getChildrenCountFunc(source);
270  for (var i = 0; i < childCount; i++)
271  {
272  var child = getChildFunc(source, i);
273  if (child != null)
274  {
275  if (child is T)
276  yield return child as T;
277 
278  foreach (var subChild in FindChildrenOfType<T>(child, getChildrenCountFunc, getChildFunc).Where(x => x != null))
279  {
280  yield return subChild;
281  }
282  }
283  }
284  }
285 
286  #endregion
287  }
288 }
static DependencyProperty[] GetDependencyProperties(this DependencyObject source, bool includingParentProperties=false)
Retrieves the public static DependencyProperties.
static DependencyObject FindFirstVisualChild(this DependencyObject source)
Gets the first visual child of the given object.
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
Definition: DirectXTexP.h:170
static Visual FindVisualRoot(this DependencyObject source)
Find the root parent that match the given type, along the visual tree.
static void DeepSetValue(this DependencyObject source, DependencyProperty property, object value)
Sets the value of a DependencyProperty on a DependencyObject and all its logical children.