Show members list in class description?

Topics: General Questions
Dec 29, 2008 at 4:59 PM

i want to use DocProject to create a printable documentation. All works nice. I excluded some stuff like the header and the feedback area but i have still about 5000 pages to print. 

The default template includes "Members" under "See also".
Is it possible to show the membe list directly in the class description at the bottom of remarks? If yes what do i need to change to show the members list directly in the class description?

Thanks a lot

Dec 30, 2008 at 9:38 AM
Edited Dec 30, 2008 at 9:41 AM


It probably depends upon the chosen presentation style, but I've worked out how to include members tables within a Class topic as new collapsible sections underneath the Remarks section for the VS2005 style:

  1. Expand your project's Help\Presentation\Style\Transforms folder in Solution Explorer.
  2. Optional: Update the globalTemplates.xsl file:
    1. Search for the comment, "a link to the type's All Members list" and surround it and all of the XSL below it (consisting of a single xsl:variable and a single xsl:if block) in <xsl:if test="not($group = 'type' and $subgroup = 'class')"> -existing stuff goes here- </xsl:if>.  This will prevent the Type Members link from appearing in the See Also section of Class topics.
  3. Optional: Update the htmlBody.xsl file:
    1. Search for the comment, "all members only" and change the value of the subsequent xsl:if element's test attribute to, "$subgroup='members' or $subgroup='class'".  This will add the bookmark links to the header for each new section as they appear in the All Members topic.
  4. Update the main_sandcastle.xsl file.
    1. Search for the term, "/remarks" to locate the placement of the remarks section (<xsl:apply-templates select="/document/comments/remarks" />).  Insert the following XSL immediately after it to include the members sections into Class topics.
    2. <!-- class members -->

      <xsl:if test="$group = 'type' and $subgroup = 'class'">

        <xsl:apply-templates select="/document/reference/elements" mode="member" />


  5. Open your project's Help\Presentation\Style\Configuration\sandcastle.help1x.config file and insert the following XML immediately after the component marked with the "Copy in reflection data" comment (typically the second component from the top of the file).
    1. Note that you'll have to add this component to the sandcastle.help2x.config file if your project builds Help 2.x output.

<!-- Copy in AllMembers elements reflection data for Class topics -->

<component type="Microsoft.Ddue.Tools.IfThenComponent" assembly="%DXROOT%\ProductionTools\BuildComponents.dll">

  <if condition="starts-with($key,'T:') and /document/reference/apidata[@subgroup = 'class']" />


    <component type="Microsoft.Ddue.Tools.CopyFromIndexComponent" assembly="%DXROOT%\ProductionTools\BuildComponents.dll">

      <copy name="reflection" key="concat('AllMembers.', $key)" source="elements" target="/document/reference" />





Please let me know if this helps.

- Dave

Dec 30, 2008 at 12:37 PM
Edited Dec 30, 2008 at 12:47 PM
Thank you for your fast reply dave. And yes it helped because it works :) I only have now one big issue... 

I would need to remove the subpage for Members because now i have redundant information in the help file.

After the modifications that make that the class members are shown below the remarks section of the class, there are still the single pages for "... members" in the help file. 

So after this modification works i only need to know how to disable those members subpages so that they arent shown in the navigation explorer... 

Thanks for your help

Dec 30, 2008 at 4:32 PM

Glad to hear that it helped :)

You can prevent those pseudo topics (as they are called in Sandcastle) from being generated altogether in a few different ways.  The problem is that these topics are depended upon by other aspects of the process, such as TOC generation.  So no matter how they are removed you'll always have to do extra work to fill in the gap when they're gone.

The first, and most perminant way for all projects, is to directly modify the ApplyVSDocModel.xsl file in Sandcastle's ProductionTransforms folder by removing the XSL under the, "all members topic" comment so that corresponding api nodes are never even generated in the reflection XML file.  You can do the same for the "list topic" comments below it as well.  I don't know what the full repercussions of taking this approach will be since I haven't tried it myself, but if you do this then I can see at least two additional steps that you must take to get my previous instructions to work correctly.  In the last step of the instructions in my first post, I included a new component into the Build Assembler configuration file.  This component pulls the elements from the AllMembers topic into Class topics, but if you remove the AllMembers topic from the reflection XML then you'll have to move the portion that generates the elements node and all of its child nodes into the UpdateTypeApiNode template.  And then you can exclude the last step of the instructions entirely since Class topics will already have the elements information included.  The second dependency on pseudo topics is the TOC generation, which relies on these topics as the containers for the actual member topics.  Without them, the member topics will not appear in the TOC.  You may be able to modify the CreateVSToc.xsl file to change the parent topic of the individual member topics, although I haven't tried myself, but again this will be a perminant change for all DocProjects being built on the system.

The first approach should help performance since it removes the extra processing that is no longer needed (e.g., including pseudo topics in the reflection file and importing elements into Class topics), but I can't say whether it's worth the effort and it may require additional effort that I haven't mentioned here to get it working properly.

Another option is to use a dynamic filter that removes pseudo topics from the reflection XML file during builds.  This may be the simplest approach, not by much though, and it does add some extra processing to builds since all of the pseudo topic information will still be added to the reflection XML file, and then removed during each build.  It also suffers from the same problem as the first approach, which is that once the AllMembers topic is removed the newly added component in the Build Assembler configuration file has nowhere from which to copy the elements node.  But this can be remedied easily using your project's Build Process Component.  Then another repercussion, as before, is that the member topics will no longer have a container in the TOC so they won't appear without some addtional modifications to the process.  The partial instructions for this approach follows.

Note that the following is an incomplete solution (depending upon your needs) since I haven't provided instructions on how to update the TOC transformation (CreateVSToc.xsl) so that it moves individual member topics under the Class topic.  If you need this functionality I can take a look to see if I can figure out the XSL when I get some time.

  1. Open Topic Explorer (via a button on the Sandcastle toolbar) and select your project in Solution Explorer.
  2. Click the filter icon in Topic Explorer's toolbar to open the Topic Filters window.
  3. Wait for the API reference TOC to be generated in Topic Explorer.  You will see a collapsed Namespaces node when it has completed.
  4. Back in the Topic Filters window, select the Regular Expression tab.
  5. Enter the following into the text area: All Members|Methods|Properties|Fields|Events
    1. Note that if you have actual API members with the same name as any of Methods, Properties, Fields or Events then they will be excluded as well.  Unlikely, but in the event that this happens you can use a dynamic Categories filter to include them back again.  If instructions are required please ask.
  6. Uncheck Find/Apply next match only above the Regluar Expression tab.
  7. Uncheck Include matching topics.
  8. Click the Apply button at the bottom-right corner of the Topic Filters window.  This is merely to test the filter to make sure that it works.  Removing psuedo topics in this way is a manual process that must be done each time new types are added to the API, but we can instead use a dynamic filter that is applied automatically during builds, as shown in the following steps.
  9. Click the Save button at the bottom-left corner.  The filter is saved and the Saved Filters tab is automatically shown.
  10. Make sure that the Build column is checked, the Include column is unchecked and that the Filter is correct.  Optionally, add a Memo describing the purpose of the filter.
  11. Click the Save All button in Visual Studio to commit the changes.  If this is the first saved filter in the project then a new dynamicFilters.xml file will be added to the Help\Settings folder to store all of your saved filters.
  12. Add an assembly reference to DaveSexton.DocProject.Sandcastle.dll, typically found in C:\Program Files\Dave Sexton\DocProject\bin.
  13. Add an assembly reference to System.Xml.dll.
    1. Note that due to a bug in Visual Studio 2008 you cannot use LINQ to XML within a VS process otherwise it will silently crash to the desktop.   (See this discussion for more information.)
  14. Open your project's Build Process Component (BuildProcess.cs|vb).
  15. Add the following using statements to the top of the file.
    1. using DaveSexton.DocProject.Sandcastle;

      using System.Xml;

  16. Replace the entire BuildStarting method with the following, which injects a dynamic build step before the dyamic filters build step to copy the elements node from the AllMembers reflection data into their corresponding Class topics' reflection data.
    1. public override void BuildStarting(BuildContext context)


        // Uncomment the following line to break into the debugger:

        // System.Diagnostics.Debugger.Break();


        buildStart = DateTime.Now;


        InsertBeforeBuildStep("Apply Dynamic Topic Filters",

          "Copy Elements from AllMembers Topics", false, false, false,




      private static void CopyElementsFromAllMembersTopics(BuildContext context)


        SandcastleBuildEngine engine = (SandcastleBuildEngine) context.Engine;

        string reflectionFile = engine.Settings.ReflectionXmlFile;



        context.TraceLine("Loading reflection file: " + reflectionFile);


        XmlDocument document = new XmlDocument();



        context.TraceLine("Importing elements from AllMembers topics...");


        foreach (XmlElement allMembers in document.SelectNodes("//api[starts-with(@id, 'AllMembers.')]"))


          XmlNode data = allMembers.SelectSingleNode("topicdata");

          string typeTopicId = data.Attributes["typeTopicId"].Value;


          XmlElement api = (XmlElement) document.SelectSingleNode("//api[@id = '" + typeTopicId + "']");


          XmlElement elements = (XmlElement) allMembers.SelectSingleNode("elements");





        context.TraceLine("Saving changes.");






  17. Undo step #5 of the instructions in my previous post.  There is no longer any need for a build component to copy the elements node from the AllMembers topic since that will be accomplished already by the code added to the Build Process Component.
- Dave
Dec 31, 2008 at 9:27 AM
Edited Dec 31, 2008 at 9:49 AM
Well this is a bit too much for this case. I know now how i can include the members list in class description. thats great for usual documentation.
But for the printing solution i need to get rid of the "Members" stuff because it makes it really big. Every class method list is printed twice (in "Members" and in "Methods"). 

I wanted to ask for "how to remove the "All members" pages. ;) Yey thanks for the regExp filters! 
I created an ^All Members$ not included filter... And edited like you described in your first reply the globalTemplates.xsl file: "Search for the comment, "a link to the type's All Members list" and uncomment it....
This works fine. looks like the constructors arent included for some reasons but this is not that important for now.
Now i have 1000 pages less to print!!! Thanks dave and a Happy New Year!