Dotneteers.net
All for .net, .net for all!

LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal

In the first two parts of this mini-series (Part 1: Hierarchy Basics, Part 2: Structure of Hierarchies) I gave you an overview about the hierarchy abstraction handled by the IVsHierarchy interface and the role of structural properties to represent parent-child relationship among nodes. In this part we dive into code to turn theory into practice.

Using the knowledge collected we start to create a simple utility called Solution Node Analyzer. With this utility we are going to be familiar with the use of IVsHierarchy in a read-only manner and prepare the way to create our own hierarchy representations.

Accessing Properties

In the first part of this series I introduced you four methods of the IVsHierarchy interface that are responsible to provide access for the arbitrary set of properties behind a hierarchy item:

int GetProperty(uint itemid, int propid, out object pvar);

int GetGuidProperty(uint itemid, int propid, out Guid pguid);

int SetProperty(uint itemid, int propid, object pvar);

int SetGuidProperty(uint itemid, int propid, ref Guid rguid);

As we saw there are two versions of property getter and setter methods: one for handling GUIDs and one for all the other objects. We also treated the meaning of method parameters:

—  itemid specifies the VSITEMID of the node we access

—  propid is an identifier for the property, there are predefined enumerations for most common IDs used within the VS Shell: __VSHPROPID, __VSHPROPID2 and __VSHPROPID3

—  The third parameter holds or retrieves the property value depending on if the method is a getter or a setter.

Till this point the picture seem to be simple, however, complications start right at this point. The devil lives in the details of what a certain property means and how it is used. The major points that cause this complexity are the followings:

—  You always need to turn to the reference documentation to find out the details about the meaning and usage of a property. Unfortunately the documentation is very succinct, so often you should make some experiments to guess out details and property semantics.

—  Property values can have different types. Sometimes property types are different than we expect. For example structural properties retrieve VSITEMID values as 32-bit signed integers while they are used (even in the getter and setter methods) as unsigned integers.

—  In case of properties retrieving COM objects you must carefully look after who is the owner of the object, who is responsible for disposing it, how the reference counting is handled.

—  There is no exact documentation about how getters and setters should work for unsupported properties.

Structural Properties

In the second part of the mini-series I illustrated how structural properties form the hierarchy of nodes in the collection of items behind an IVsHierarchy instance. The IDs of structural properties are defined in the __VSHPROPID enumeration. I summarize them in the table below. When I use the term “node” in the table I always mean the node within the collection of hierarchy items having the ID passed in the itemid parameter of the getter or setter.

ID

Description

VSHPROPID_Parent

The VSITEMID of the node’s parent item. For example, in projects a folder node is the parent of the files put into that folder. The property uses a System.Int32 value. If the node is a direct parent of the root node, VSITEMID_ROOT is retrieved. If the node is at the root level and it does not have a parent, VSITEMID_NIL is returned.

VSHPROPID_FirstChild

The VSITEMID of the first child parented by the node in the physical layout of the hierarchy. The property uses a System.Int32 value. If the node is a leaf node and so does not have children VSITEMID_NIL is returned.

VSHPROPID_NextSibling

The VSITEMID of the next sibling node in the physical layout of the hierarchy. The property uses a System.IntPtr value. If the node is the last one on its parent’s siblings list, a VSITEMID_NIL value is returned.

VSHPROPID_FirstVisibleChild

The VSITEMID of the first visible child parented by the node in the visual layout of the hierarchy. The property uses a System.Int32 value. If the node is a leaf node and so does not have children VSITEMID_NIL is returned.

VSHPROPID_NextVisibleSibling

The VSITEMID of the next visible sibling node in the visual layout of the hierarchy. The property uses a System.IntPtr value. If the node is the last one on its parent’s siblings list, a VSITEMID_NIL value is returned.

VSHPROPID_ParentHierarchy

The IVsHierarchy instance owning the hierarchy of the node. If the hierarchy is not owned (nested) by any other hierarchy this property retrieves null. You can use this property for any node in the hierarchy; they will return the same parent as if you would use it for the root node.

VSHPROPID_ParentHierarchyItemid

Nested (shortcut) hierarchies have an invisible node in their parent hierarchy that holds the shortcut to the root node of the nested hierarchy. This property retrieves a System.IntPtr value telling the VSITEMID of the node holding the shortcut. It does not seem logical, but you can use this property for any node in the hierarchy. The property value is the same VSITEMID as if you would use it only for the root node. Please note, this VSITEMID has valid meaning only in the IVsHierarchy of the parent hierarchy.

Furthermore when I use a property identifier I will omit the VSHPROPID_ prefixes from the names as they do not tell too much.

From the table above you can see that handling VSITEMID values is slightly chaotic. FirstChild and FirstVisibleChild use a System.Int32 type while NextSibling, NextVisibleSibling and ParentHierarchyItemId properties use System.IntPtr. As another twist we pass System.UInt32 instances for VSITEMIDs in the property getter and setter methods.

Creating a Solution Node Analyzer Utility

All information I share with you about hierarchies are rather coming from experiments and not from the documentation I could access. To guess out how the hierarchy system works, I created a VSPackage with VSXtra called SolutionNodeAnalyzer. During writing these posts this utility continuously changes as I find some new field to discover. As I move on I create useful types that make it easier to use and understand hierarchies.

This UI of the utility looks like this:

The Solution Node Analyzer tool window contains a list with the physical layout of the currently loaded solution hierarchy. As you select one item in the list, you can see all the properties of the related item in the Properties window.

In this post I will not tell you all details about the creation of this utility. If you want to obtain the full source code you can download if from the VSXtra project. In this post I will focus on handling the structural properties and traversing the solution tree.

We are going to look into the details about the following things:

—  How VSITEMID properties can be represented?

—  How to wrap structural properties into a class?

—  How to traverse the solution tree?

Representing VSITEMID Properties

We could see above that a VSITEMID value is represented by (at least) three types when using the IVsHierarchy interface:

—  With System.UInt32 when calling the getter and setter methods

—  With System.Int32 when using the FirstChild and FirstVisibleChild properties

—  With System.IntPtr in case of NextSibling, NextVisibleSibling and ParentHierarchyItemID.

Would not be it nice to have a type representing VSITEMID values in order to hide this annoying issue? I have created two types to help the situation. The HierarchyId is to represent VSITEMID values while the HierarchyItemIdTypeConverter provides the functionality to display friendly VSITEMID values in the Properties window.

HierarchyId definition is simple:

[TypeConverter(typeof(HierarchyIdTypeConverter))]

public struct HierarchyId

{

  private readonly uint _Id;

 

  public static HierarchyId Root = new HierarchyId(VSConstants.VSITEMID_ROOT);

  public static HierarchyId Nil = new HierarchyId(VSConstants.VSITEMID_NIL);

  public static HierarchyId Selection =

    new HierarchyId(VSConstants.VSITEMID_SELECTION);

 

  public HierarchyId(uint id)

  {

    _Id = id;

  }

 

  public HierarchyId(int id)

  {

    _Id = (uint)id;

  }

HierarchyId is a struct emphasizing that a VSITEMID is a value. This class provides constructors for creating the ID from both System.Int32 and System.UInt32. The System.IntPtr contains an explicit cast operator to System.Int32, so I made the decision that I do not provide a constructor for it.

Root, Nil and Selection static fields provide “shortcuts” for often used values.

  public uint Value

  {

    get { return _Id; }

  }

 

  public bool IsNil

  {

    get { return _Id == Nil._Id; }

  }

 

  public bool IsRoot

  {

    get { return _Id == Root._Id; }

  }

 

  public bool IsSelection

  {

    get { return _Id == Selection._Id; }

  }

We can access the System.UInt32 value behind the VSITEMID and can check if those are one of the predefined values.

  public static explicit operator int(HierarchyId id)

  {

    return (int) id._Id;

  }

 

  public static explicit operator uint(HierarchyId id)

  {

    return id._Id;

  }

 

  public static implicit operator HierarchyId(int id)

  {

    return new HierarchyId(id);

  }

 

  public static implicit operator HierarchyId(uint id)

  {

    return new HierarchyId(id);

  }

I provided a few operators to cast HierarchyId values to int and uint, and vice versa.

  public override string ToString()

  {

    if (_Id == VSConstants.VSITEMID_ROOT) return "ROOT";

    if (_Id == VSConstants.VSITEMID_NIL) return "NIL";

    if (_Id == VSConstants.VSITEMID_NIL) return "SELECTION";

    return _Id.ToString();

  }

 

  public static bool TryParse(string value, out HierarchyId id)

  {

    if (String.Compare("root", value, true) == 0)

    {

      id = Root;

      return true;

    }

    if (String.Compare("nil", value, true) == 0)

    {

      id = Nil;

      return true;

    }

    if (String.Compare("selection", value, true) == 0)

    {

      id = Selection;

      return true;

    }

    int intId;

    if (Int32.TryParse(value, out intId))

    {

      id = new HierarchyId(intId);

      return true;

    }

    uint uintId;

    if (UInt32.TryParse(value, out uintId))

    {

      id = new HierarchyId(uintId);

      return true;

    }

    id = Nil;

    return false;

  }

 

  public static HierarchyId Parse(string value)

  {

    HierarchyId result;

    if (TryParse(value, out result)) return result;

    throw new InvalidCastException();

  }

}

Just as for other common value types I provided methods to convert HierarchyId values to strings and parse strings as HierarchyId values.

The HierarchyIdTypeConverter helps to display VSITEMID values in the properties window:

public class HierarchyIdTypeConverter : TypeConverter

{

  public override bool CanConvertFrom(ITypeDescriptorContext context,

    Type sourceType)

  {

    if (sourceType == typeof(string) || sourceType == typeof(int) ||

      sourceType == typeof(uint)) return true;

    return base.CanConvertFrom(context, sourceType);

  }

 

  public override bool CanConvertTo(ITypeDescriptorContext context,

    Type destinationType)

  {

    if (destinationType == typeof(string) || destinationType == typeof(int) ||

      destinationType == typeof(uint)) return true;

    return base.CanConvertTo(context, destinationType);

  }

 

  public override object ConvertFrom(ITypeDescriptorContext context,

    CultureInfo culture, object value)

  {

    if (value is int) return new HierarchyId((int) value);

    if (value is uint) return new HierarchyId((uint) value);

    var strValue = value as string;

    if (strValue != null) return HierarchyId.Parse(strValue);

    return base.ConvertFrom(context, culture, value);

  }

 

  public override object ConvertTo(ITypeDescriptorContext context,

    CultureInfo culture, object value, Type destinationType)

  {

    if (!(value is HierarchyId)) return null;

    var hierValue = (HierarchyId) value;

    if (destinationType == typeof(int)) return (int)hierValue;

    if (destinationType == typeof(uint)) return (uint)hierValue;

    if (destinationType == typeof(string)) return hierValue.ToString();

    return base.ConvertTo(context, culture, value, destinationType);

  }

}

Wrapping Structural Properties into a Class

The .NET framework defines the concept of properties, so it is a natural wish that we would like to access structural properties through this mechanism instead of using the GetProperty and SetProperty methods. I created the HierarchyItem class to read IVsHierarchy properties in this natural way.

public class HierarchyItem: CustomTypeDescriptorBase

{

  private readonly IVsHierarchy _Hierarchy;

  private readonly uint _ItemId;

 

  public HierarchyItem(IVsHierarchy hierarchy, uint itemId)

  {

    _Hierarchy = hierarchy;

    _ItemId = itemId;

  }

 

  [Browsable(false)]

  public IVsHierarchy Hierarchy

  {

    get { return _Hierarchy; }

  }

 

  [DisplayName("ID")]

  [Category("Identification")]

  [Description("Item ID within the hierarchy.")]

  public HierarchyId Id

  {

    get { return _ItemId; }

  }

A HierarchyItem instance wraps a hierarchy node represented by its IVsHierarchy instance and the item identifier of the node. Our class derives from the CustomTypeDescriptorBase class in order to allow friendly appearance in the Properties window.

  [DisplayName("Parent Node ID")]

  [Category("Hierarchy info")]

  [Description("Item ID of the parent node; VSITEMID_NIL, if no parent.")]

  public HierarchyId ParentId

  {

    get { return GetProperty<int>(__VSHPROPID.VSHPROPID_Parent); }

  }

We use the GetProperty<> generic method to access an IVsHierarchy property (declared later in this class).

  [DisplayName("Name")]

  [Category("Names and Paths")]

  [Description("Name of the item.")]

  public string Name

  {

    get { return GetProperty<string>(__VSHPROPID.VSHPROPID_Name); }

  }

I did not mention it before, but we can access to the Name of the hierarchy item by using the VSHPROPID_Name property ID.

  [Browsable(false)]

  public HierarchyItem ParentHierarchy

  {

    get

    {

      var parentHierarchy = GetProperty(__VSHPROPID.VSHPROPID_ParentHierarchy)

        as IVsHierarchy;

      return parentHierarchy == null

        ? null

        : new HierarchyItem(parentHierarchy, VSConstants.VSITEMID_ROOT);

    }

  }

Our node may have a parent hierarchy. If it has, we wrap it into a new HierarchyItem instance.

  [DisplayName("Item ID in Parent Hierarchy")]

  [Category("Identification")]

  [Description("If the current hierachy is nested into a parent hierarchy, " +

    "this value tells the ID used in the parent hierarchy.")]

  public HierarchyId ParentHierarchyItemId

  {

    get

    {

      object id = GetProperty(__VSHPROPID.VSHPROPID_ParentHierarchyItemid);

      if (id is int) return (uint) (int) id;

      if (id is uint) return (uint) id;

      return HierarchyId.Nil;

    }

  }

If the node does not have a parent hierarchy, it does not have an ID in the parent hierarchy and so we return a Nil value.

  [DisplayName("Is Nested Hierarchy?")]

  [Category("Hierarchy info")]

  [Description("This flag tells if this hierarchy item is nested into an " +

    "owner hierarchy or not.")]

  public bool IsNestedHierachy

  {

    get { return Id.IsRoot && !ParentHierarchyItemId.IsNil; }

  }

We can check if a node has a nested hierarchy or not. In our definition only the root node can be taken into account as a nested hierarchy.

  [DisplayName("First Child ID")]

  [Category("Hierarchy info")]

  [Description("Item ID of the first child node; VSITEMID_NIL, if this item" +

    " has no children.")]

  public HierarchyId FirstChild

  {

    get { return GetProperty<int>(__VSHPROPID.VSHPROPID_FirstChild); }

  }

 

  [DisplayName("First Visible Child ID")]

  [Category("Hierarchy info")]

  [Description("Item ID of the first visible child node; VSITEMID_NIL, " +

    "if this item has no visible children.")]

  public HierarchyId FirstVisibleChild

  {

    get { return GetProperty<int>(__VSHPROPID.VSHPROPID_FirstVisibleChild); }

  }

 

  [DisplayName("Next Sibling ID")]

  [Category("Hierarchy info")]

  [Description("Item ID of the subsquent sibling of this item; " +

    "VSITEMID_NIL, if this item has no more siblings.")]

  public HierarchyId NextSibling

  {

    get { return GetProperty<int>(__VSHPROPID.VSHPROPID_NextSibling); }

  }

 

  [DisplayName("Next Visible Sibling ID")]

  [Category("Hierarchy info")]

  [Description("Item ID of the subsquent visible sibling of this item; " +

    "VSITEMID_NIL, if this item has no more siblings.")]

  public HierarchyId NextVisibleSibling

  {

    get { return GetProperty<int>(__VSHPROPID.VSHPROPID_NextVisibleSibling); }

  }

The properties above define the ones describing the parent-child relations of the physical and visual layout of the hierarchy.

  protected T GetProperty<T>(__VSHPROPID propId)

  {

    return (T)GetProperty(propId);

  }

 

  protected T GetProperty<T>(int propId)

  {

    return (T)GetProperty(propId);

  }

 

  protected object GetProperty(__VSHPROPID propId)

  {

    return GetProperty((int) propId);

  }

 

  protected object GetProperty(int propId)

  {

    if (propId == (int)__VSHPROPID.VSHPROPID_NIL) return null;

    object propValue;

    _Hierarchy.GetProperty(_ItemId, propId, out propValue);

    return propValue;

  }

The GetProperty helper methods defined above are the keys to access the hierarchy properties.

  protected override string ComponentName

  {

    get { return string.IsNullOrEmpty(Name) ? "<none>" : Name; }

  }

}

The overridden ComponentName property sets the name appearing in the component combo box of the Properties window.

If you download the source code of the Solution Node Analyzer utility, you’ll find some more properties within the HierarchyItem class.

Solution Tree Traversal

We have created all the main pieces to discover the solution hierarchy; it is time to see how to traverse a hierarchy tree. To create the code for solution traversal I started from the VS SDK sample named SolutionHierarchyTraversal.

The static Solution class of VSXtra contains the following method to traverse the hierarchy node:

public static IEnumerable<HierarchyTraversalInfo> TraverseItems();

The method returns a collection of HierarchyTraversalInfo instances in DFS (depth-first-search) order. HierarchyTraversalInfo adds depth information to a HierarchyItem instance:

public class HierarchyTraversalInfo

{

  public HierarchyItem HierarchyNode { get; private set; }

  public int Depth { get; private set; }

 

  public HierarchyTraversalInfo(HierarchyItem hierarchyNode, int depth)

  {

    HierarchyNode = hierarchyNode;

    Depth = depth;

  }

 

  public HierarchyTraversalInfo(IVsHierarchy hierarchyNode, uint itemId,

    int depth)

  {

    HierarchyNode = new HierarchyItem(hierarchyNode, itemId);

    Depth = depth;

  }

}

Now let’s see, how TraverseItems work!

public static IEnumerable<HierarchyTraversalInfo> TraverseItems()

{

  if (_Solution == null) yield break;

  var solutionHierarchy = _Solution as IVsHierarchy;

  if (null != solutionHierarchy)

  {

    foreach (var item in TraverseHierarchyItem(solutionHierarchy,

      VSConstants.VSITEMID_ROOT, 0, true))

    {

      yield return item;

    }

  }

}

The _Solution member field holds an IVsSolution instance. This is a singleton instance within a VS IDE process. IVsSoultion is responsible for managing the currently loaded solution (or load a solution). The object implementing the IVsSolution interface is also assumed to support IVsHierarchy. The current traversal is carried out by the TraverseHierarchyItem method. We pass the root of the hierarchy (the solution node) and return its result.

TraverseHierarchyItem has a few arguments:

private static IEnumerable<HierarchyTraversalInfo> TraverseHierarchyItem(

  IVsHierarchy hierarchy,

  uint itemid,

  int recursionLevel,

  bool hierIsSolution);

The hierarchy and itemid parameters define the hierarchy node we intend to discover. The recursionLevel value indicates the depth of the starting node in the solution hierarchy (as you obviously guessed out we use recursion for DFS traversal). There is a bug in VS 2005 and earlier versions (I have not checked if it is already in VS 2008) and we need the hierIsSolution flag to be able to use a workaround. This flag indicates whether the starting node is the solution node or not.

Now, let’s see the details:

private static IEnumerable<HierarchyTraversalInfo> TraverseHierarchyItem(

  IVsHierarchy hierarchy,

  uint itemid,

  int recursionLevel,

  bool hierIsSolution)

{

  IntPtr nestedHierarchyObj;

  uint nestedItemId;

  var hierGuid = typeof(IVsHierarchy).GUID;

 

  var hr = hierarchy.GetNestedHierarchy(itemid, ref hierGuid,

    out nestedHierarchyObj, out nestedItemId);

  if (VSConstants.S_OK == hr && IntPtr.Zero != nestedHierarchyObj)

  {

    var nestedHierarchy = Marshal.GetObjectForIUnknown(nestedHierarchyObj)

      as IVsHierarchy;

    Marshal.Release(nestedHierarchyObj);

    if (nestedHierarchy != null)

    {

      foreach (var item in TraverseHierarchyItem(nestedHierarchy, nestedItemId,

        recursionLevel, false))

      {

        yield return item;

      }

    }

  }

A hierarchy node can have a shortcut to a root node of another hierarchy (we call it nested hierarchy). If the node has a nested hierarchy, we want to traverse that hierarchy from its root. The GetNestedHierarchy method of the IVsHierarchy is the key to check it. In the first parameter we pass the VSITEMID of the node. The second parameter is a GUID. It defines type identifier of an interface we expect the requested hierarchy to support. We expect an IVsHierarchy-aware node instance, so we pass the typeof(IVsHierarchy).GUID value. The two output parameters return the information required to access the nested hierarchy node. The nestedHierarchyObj is a pointer to the hierarchy. Its IntPtr.Zero value means the node does not have a shortcut to another hierarchy. The nestedItemId is the identifier of the node in the nested hierarchy linked to our node. Although IVsHierarchy is set up to support shortcutting to any node in another hierarchy, the environment currently only supports shortcutting to the root node of the nested hierarchy. We can expect the VSITEMID_ROOT value to be retrieved.

Because the nested hierarchy node is retrieved back as a System.IntPtr, we must obtain the IVsHierarchy instance using Marshal methods. Please note, we incremented reference counter of the COM object behind the System.IntPtr value when calling Marshal.GetObjectForIUnknown, so we must release this object in order to decrement the counter. If we managed to obtain an IVSHierarchy instance, we traverse that recursively.

In the mean time the nodes do not have nested hierarchies. In this case we retrieve the current item and traverse its children recursively:

  else

  {

    yield return new HierarchyTraversalInfo(hierarchy, itemid, recursionLevel);

    recursionLevel++;

 

    object pVar;

    hr = hierarchy.GetProperty(itemid,

      (hierIsSolution && recursionLevel == 1)

         ? (int) __VSHPROPID.VSHPROPID_FirstVisibleChild

         : (int) __VSHPROPID.VSHPROPID_FirstChild,

      out pVar);

In the code above we use a workaround due to a bug in the Solution implementation of the VSHPROPID_FirstChild property. The bug is that the solution improperly enumerates nested projects in the solution if they are immediate children of the solution. Fortunately, the VSHPROPID_FirstVisibleChild implementation is correct. Because we cannot hide a project or solution folder node in the VS IDE (there is no such feature), we can use the FirstVisibleChild property instead of FirstChild if we are just directly under the solution level.

    ErrorHandler.ThrowOnFailure(hr);

    if (VSConstants.S_OK == hr)

    {

      var childId = GetItemId(pVar);

      while (childId != VSConstants.VSITEMID_NIL)

      {

        foreach (var item in TraverseHierarchyItem(hierarchy, childId,

          recursionLevel, false))

        {

          yield return item;

        }

 

        hr = hierarchy.GetProperty(childId,

          (hierIsSolution && recursionLevel == 1)

             ? (int)__VSHPROPID.VSHPROPID_NextVisibleSibling

             : (int)__VSHPROPID.VSHPROPID_NextSibling,

           out pVar);

        if (VSConstants.S_OK == hr)

        {

          childId = GetItemId(pVar);

        }

        else

        {

          ErrorHandler.ThrowOnFailure(hr);

          break;

        }

      }

    }

  }

}

We traverse the child recursively (if there is any) and then go on to the next child (the next sibling node of the child we traversed last time). Here we make the same workaround for the NextSibling property as for the FirstChild property before.

During the traversal we used the VSITEMID obtained through the IVsHierarchy.GetProperty method. The GetItemId helper cares about converting it to a System.UInt32 value:

private static uint GetItemId(object pvar)

{

  if (pvar == null) return VSConstants.VSITEMID_NIL;

  if (pvar is int) return (uint)(int)pvar;

  if (pvar is uint) return (uint)pvar;

  if (pvar is short) return (uint)(short)pvar;

  if (pvar is ushort) return (ushort)pvar;

  if (pvar is long) return (uint)(long)pvar;

  return VSConstants.VSITEMID_NIL;

}

Where we are?

In this post we saw how to access structural properties of a hierarchy node. We started to create a Solution Node Analyzer utility helping us to discover solution items and their properties.

With a few helper classes we created IVsHierarchy wrappers that allow using hierarchy items in a managed way instead of the original semantics. We also saw how to traverse a hierarchy in a DFS order.

In the next part we are going to discover a few more properties and start using the utility to look behind hierarchies.


Posted Oct 16 2008, 10:46 AM by inovak
Filed under: , ,

Comments

Visual Studio Hacks wrote Visual Studio Links #78
on Thu, Oct 16 2008 14:36

My latest in a series of the weekly, or more often, summary of interesting links I come across related to Visual Studio. Channel 9 Stuff: Anders Hejlsberg and Guy Steele- Concurrency and Language Design The Concurrency Runtime- Fine Grained Parallelism

Amir wrote re: LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal
on Thu, Nov 6 2008 15:41

This is excatly what i was looking for, Thanks :)

Great POST!

Websites tagged "instances" on Postsaver wrote Websites tagged "instances" on Postsaver
on Sat, Feb 14 2009 9:32

Pingback from  Websites tagged "instances" on Postsaver

Mihai wrote re: LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal
on Wed, Apr 15 2009 16:28

Where is the VSExtra project source code exactly ?

About IVsHierarchy Structure for VSPackage Development « ????????????????????? wrote About IVsHierarchy Structure for VSPackage Development &laquo; ?????????????????????
on Fri, Apr 22 2011 11:43

Pingback from  About IVsHierarchy Structure for VSPackage Development « ?????????????????????

Gustavo wrote re: LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal
on Wed, Jun 15 2011 17:23

Hi man, very cool post. Where can I get the source code for this?

Thanks

Marie wrote re: LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal
on Sat, Nov 17 2012 8:25

No the node does not copy itself.The point of the likend list is to have a node refer to the next in line.So if you have 3 items in a likendlist, the first node has a reference to the second, and the second to the third.Node one = new Node(1);one.appendToTail(2);will result in node one, having created a new node, and put it in it's next fieldone.next.data will be equal to 2.one.appendToTail(3)will result in node one referring to node 2, and node 2 will create node 3, and set it as it's next field.one.data == 1one.next.data == 2one.next.next.data == 3The loop is basically to search the last node in line (because it has it's next set to null).

buy imitrex generic wrote re: LearnVSXNow! Part #36 - Working with Hierarchies Part 3 - Properties and Hierarchy Traversal
on Fri, Feb 15 2013 20:00

bMWGWq Hey, thanks for the post.