And the revised version that doesn’t exhibit the excessive memory consumption issue mentioned in my previous post.
import System; import System.Text; import System.Windows; import System.Windows.Controls; import System.Windows.Media; import System.Windows.Media.Media3D; import System.Reflection; import MForms; package MForms.JScript { class VTWalker { public function Init(element: Object, args: Object, controller : Object, debug : Object) { var sbBuilder : StringBuilder = new StringBuilder(5000); // this is a grid that appears on our panel, interestingly it doesn't include some of the higher // level controls on the main panel var content : Object = controller.RenderEngine.Content; // to prove that we are indeed a Grid. //debug.WriteLine("content object type = " + content.GetType().ToString()); var parent : Object = content; var lastParent : Object = content; // here we will loop UP the VisualTree seeking the top while(null != (parent = VisualTreeHelper.GetParent(parent))) { lastParent = parent; } //debug.WriteLine(" ************ "); //debug.WriteLine(" ************ "); //debug.WriteLine("From Grid downwards"); // output the tree from the Grid down, if you want to // go from the very highest Parent, then change content to lastParent displayChildren(sbBuilder, lastParent, 1, debug); debug.WriteLine(sbBuilder.ToString()); // debug.WriteLine("Finished, debug object type = " + debug.GetType().ToString()); } // displayChildren // display information for each of the objects children // recurse down the tree // parent - the object whose children we want to investigate // depth - we keep track of the depth so we can indent our output to make reading easier // debug - so we can output our data private function displayChildren(sbBuilder : StringBuilder, parent : Object, depth : int, debug : Object) { try { if(null != parent) { // get the type of our object, we do this // so we can check if the object inherits // from a DependencyObject var parentobjType : Type = parent.GetType(); if(parentobjType.IsSubclassOf(DependencyObject) == true) { // loop through the children of this object for(var i=0; i < VisualTreeHelper.GetChildrenCount(parent);i++) { // retrieve the child object var current : Object = VisualTreeHelper.GetChild(parent,i); if(null != current) { // here we shall deterine the type of the new object var objType = current.GetType(); // we're looking for the Name property, because // this is what I am interested in var objPropertyInfo = objType.GetProperty("Name"); var objPropertyVisible = objType.GetProperty("Visibility"); // strPadding allows us to indent var strPadding : String = ""; for(var j = 0; j < (depth * 4); j++) { strPadding += " "; } // if objPropertyInfo is null then // we couldn't find the Name property if(null != objPropertyInfo) { // output the name of the object //debug.WriteLine(strPadding + "Object name: " + objPropertyInfo.GetValue(current)); sbBuilder.Append(strPadding + "Object name: " + objPropertyInfo.GetValue(current)); sbBuilder.Append(Environment.NewLine); } else { //debug.WriteLine(strPadding + "Object name: Unknown"); } // output the objects type //debug.WriteLine(strPadding + "Object Type: " + objType.ToString()); sbBuilder.Append(strPadding + "Object Type: " + objType.ToString()); sbBuilder.Append(Environment.NewLine); if(null != objPropertyVisible) { //debug.WriteLine(strPadding + "Object Visibility: " + objPropertyVisible.GetValue(current).ToString()); sbBuilder.Append(strPadding + "Object Visibility: " + objPropertyVisible.GetValue(current).ToString()); sbBuilder.Append(Environment.NewLine); } // does the current object have any children? if(VisualTreeHelper.GetChildrenCount(current) >= 1) { // recurse down displayChildren(sbBuilder, current, depth+1, debug); } } } } } } catch(ex) { debug.WriteLine("!-! Exception: " + ex.Message + " " + ex.StackTrace); } } } }