Created
January 16, 2012 23:16
-
-
Save murven/1623532 to your computer and use it in GitHub Desktop.
WPF - Dependency object extensions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class DependencyObjectExtensions | |
{ | |
/// <summary> | |
/// Creates a new instance of the same type and copies all properties and values. | |
/// </summary> | |
/// <typeparam name="T">A type that extends DependencyObject</typeparam> | |
/// <param name="source"></param> | |
/// <returns>A new instance that represents a copy of the properties and values of the original instance.</returns> | |
public static T Clone<T>(this T source) where T : DependencyObject | |
{ | |
Type t = source.GetType(); | |
T no = (T)Activator.CreateInstance(t); | |
Type wt = t; | |
while (wt.BaseType != typeof(DependencyObject)) | |
{ | |
FieldInfo[] fi = wt.GetFields(BindingFlags.Static | BindingFlags.Public); | |
for (int i = 0; i < fi.Length; i++) | |
{ | |
{ | |
DependencyProperty dp = fi[i].GetValue(source) as DependencyProperty; | |
if (dp != null && fi[i].Name != "NameProperty") | |
{ | |
DependencyObject obj = source.GetValue(dp) as DependencyObject; | |
if (obj != null) | |
{ | |
object o = obj.Clone(); | |
no.SetValue(dp, o); | |
} | |
else | |
{ | |
if (fi[i].Name != "CountProperty" && | |
fi[i].Name != "GeometryTransformProperty" && | |
fi[i].Name != "ActualWidthProperty" && | |
fi[i].Name != "ActualHeightProperty" && | |
fi[i].Name != "MaxWidthProperty" && | |
fi[i].Name != "MaxHeightProperty" && | |
fi[i].Name != "StyleProperty") | |
{ | |
no.SetValue(dp, source.GetValue(dp)); | |
} | |
} | |
} | |
} | |
} | |
wt = wt.BaseType; | |
} | |
PropertyInfo[] pis = t.GetProperties(); | |
for (int i = 0; i < pis.Length; i++) | |
{ | |
if ( | |
pis[i].Name != "Name" && | |
pis[i].Name != "Parent" && | |
pis[i].Name != "TargetType" && | |
pis[i].CanRead && pis[i].CanWrite && | |
!pis[i].PropertyType.IsArray && | |
!pis[i].PropertyType.IsSubclassOf(typeof(DependencyObject)) && | |
pis[i].GetIndexParameters().Length == 0 && | |
pis[i].GetValue(source, null) != null && | |
pis[i].GetValue(source, null) != (object)default(int) && | |
pis[i].GetValue(source, null) != (object)default(double) && | |
pis[i].GetValue(source, null) != (object)default(float) | |
) | |
pis[i].SetValue(no, pis[i].GetValue(source, null), null); | |
else if (pis[i].PropertyType.GetInterface("IList", true) != null) | |
{ | |
int cnt = (int)pis[i].PropertyType.InvokeMember("get_Count", BindingFlags.InvokeMethod, null, pis[i].GetValue(source, null), null); | |
for (int c = 0; c < cnt; c++) | |
{ | |
object val = pis[i].PropertyType.InvokeMember("get_Item", BindingFlags.InvokeMethod, null, pis[i].GetValue(source, null), new object[] { c }); | |
object nVal = val; | |
DependencyObject v = val as DependencyObject; | |
if (v != null) | |
nVal = v.Clone(); | |
if (pis[i].GetValue(no, null) == null) | |
{ | |
object obj = Activator.CreateInstance(pis[i].PropertyType); | |
pis[i].SetValue(no, obj, null); | |
} | |
pis[i].PropertyType.InvokeMember("Add", BindingFlags.InvokeMethod, null, pis[i].GetValue(no, null), new object[] { nVal }); | |
} | |
} | |
} | |
return no; | |
} | |
/// <summary> | |
/// Finds the first child in the visual tree matching the specified type. | |
/// </summary> | |
/// <typeparam name="T">A type that extends DependencyObject</typeparam> | |
/// <param name="parent"></param> | |
/// <returns>The first child found in the visual tree matching the specified type. Null if the child was not found.</returns> | |
public static T FindVisualChild<T>(this DependencyObject parent, string childName = null) where T : DependencyObject | |
{ | |
int count = VisualTreeHelper.GetChildrenCount(parent); | |
for (int i = 0; i < count; i++) | |
{ | |
var child = VisualTreeHelper.GetChild(parent, i); | |
var childElement = child as FrameworkElement; | |
if (child is T && (childName == null || (childElement != null && childElement.Name == childName))) | |
{ | |
return child as T; | |
} | |
else | |
{ | |
var grandchild = child.FindVisualChild<T>(childName); | |
if (grandchild is T) | |
{ | |
return grandchild; | |
} | |
} | |
} | |
return null; | |
} | |
/// <summary> | |
/// Finds the first parent in the visual tree matching the specified type. | |
/// </summary> | |
/// <typeparam name="T">A type that extends DependencyObject</typeparam> | |
/// <param name="child"></param> | |
/// <returns>The first parent found in the visual tree matching the specified type. Null if the type was not found.</returns> | |
public static T FindVisualParent<T>(this DependencyObject child, string parentName = null) where T : DependencyObject | |
{ | |
var parent = VisualTreeHelper.GetParent(child); | |
if (parent == null) | |
{ | |
return null; | |
} | |
else | |
{ | |
var parentElement = parent as FrameworkElement; | |
if (parent is T && (parentName == null || (parentElement != null && parentElement.Name == parentName))) | |
{ | |
return parent as T; | |
} | |
else | |
{ | |
return parent.FindVisualParent<T>(parentName); | |
} | |
} | |
} | |
/// <summary> | |
/// Finds the first child in the visual tree matching the specified type. | |
/// </summary> | |
/// <typeparam name="T">A type that extends DependencyObject</typeparam> | |
/// <param name="parent"></param> | |
/// <returns>The first child found in the visual tree matching the specified type. Null if the child was not found.</returns> | |
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject parent) where T : DependencyObject | |
{ | |
int count = VisualTreeHelper.GetChildrenCount(parent); | |
for (int i = 0; i < count; i++) | |
{ | |
var child = VisualTreeHelper.GetChild(parent, i); | |
if (child is T) | |
{ | |
yield return child as T; | |
} | |
var grandchildren = child.FindVisualChildren<T>(); | |
foreach (var grandchild in grandchildren) | |
{ | |
yield return grandchild; | |
} | |
} | |
} | |
public static Panel FindPanel(this DependencyObject element) | |
{ | |
var childrenCount = VisualTreeHelper.GetChildrenCount(element); | |
for (Int32 i = 0; i < childrenCount; i++) | |
{ | |
var child = VisualTreeHelper.GetChild(element, i); | |
if (child is Panel) | |
{ | |
return child as Panel; | |
} | |
else | |
{ | |
child = FindPanel(child); | |
if (child is Panel) | |
{ | |
return child as Panel; | |
} | |
} | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment