/// <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);
        }