Skip to content

Instantly share code, notes, and snippets.

@murven
Created January 16, 2012 23:16
Show Gist options
  • Save murven/1623532 to your computer and use it in GitHub Desktop.
Save murven/1623532 to your computer and use it in GitHub Desktop.
WPF - Dependency object extensions
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