Click here to Skip to main content
15,867,957 members
Articles / Web Development / HTML

Writing a XAML application for X11 and Windows to create HTML help for assemblies

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
24 Mar 2017CPOL15 min read 13K   246   3   1
This article introduces a small tool (much simpler than sandcaste help file builder) to create HTML help for .NET/MONO assemblies and reviews the XAML based approach to create GUI application with the Roma Widget Set XrwXAML.

Image 1 Download complete X11_32 project, older version: 0.10, 0.20
Image 2 Download complete X11_64 project, older version: 0.10, 0.20
Image 3 Download complete Win10_64 project, older version: 0.10, 0.20

Image 4 Download XamlDocer_V0.30_X11_32.zip Mono solution including full source and executable
Image 5 Download XamlDocer_V0.30_X11_64.zip Mono solution including full source and executable
Image 6 Download XamlDocer_V0.30_Win10.zip Visual Studio 2015 solution including full source and executable

Introduction

Incentive

Since Sandcastle is limited to the Windows® platform, there is a lack for Linux/Unix users, programming with MONO, to have a documentation generator, automatically producing code documentation out of reflection information for .NET/MONO assemblies and XML documentation comments found in the source code of these assemblies.

This application, XamlDocer, might fill the lack. I'll try to enhance XamlDocer to a full-featured tool step by step - keep watching for updates, if you are interested.

There are alternatives, that support Unix/Linux and C# and should not be unmentioned here:

  • Doxygen (uses a different syntax to comment)
  • Natural Docs (uses a different syntax to comment)
  • NDoc (seems to be inactice for a while)

If you just want to test/use this little tool for your purposes, go ahead to chapter Usage.

Beside the assistance of your dayly development

This article is also a case study, how to write a MVVM (Model View ViewModel) design pattern based X11/Windows (cross platform) application (utilizing .NET reflection to generate HTML help for .NET/MONO assemblies) with XAML using the Roma Widget Set (Xrw). The Roma Widget Set is a zero dependency GUI application framework for X11 (it requires only assemblies of the free Mono standard installation and libraries of the free X11 distribution; it doesn't particularly require GNOME, KDE or commercial libraries) and is implemented entirely in C#.

This article continues the works Writing a XAML dialog application for X11, Writing a XAML ribbon application for X11, Writing a XAML application for X11 with massive data binding and zero code, Writing a XAML calculator application for X11, Writing a XAML application with geometry objects (shapes) for X11, Writing a XAML application for X11 with UserControls, Writing a XAML 7 segment LCD display UserControl for X11 and Windows, Writing a XAML Minesweeper game for X11 and Windows and Writing a XAML application for X11 and Windows drawing a chessboard to demonstrate DrawingBrush. As far as i know, this (utilizing the Xrw) is the first attempt to use XAML for X11 application development after the abandonment of Moonlight.

Neither the Roma Widget Set nor the XAML implementation are complete. This sample application is intended as a more complex 'proof of concept' and checks out if and how it is possible bo create MVVM design pattern based X11/Windows (cross platform) application with XAML.

Since this tenth attempt to use XAML for a X11 application development has been successful, other articles about XAML using the Roma Widget Set on X11 will follow centenly.

Background

The Motivation and the general Concept to use XAML for X11 application development are already explained in the Writing a XAML dialog application for X11 article.

The RelayCommand approach and the usage of ViewModel class have already been introduced in the Writing a XAML ribbon application for X11 article.

The DependencyProperty bindings have been completely reworked since the release of Xrw version 0.9 and this demonstration application utilizes the new bindings to realize the complete communication between View and ViewModel. Different to older XAML demonstration applications for Xrw the View and ViewModel communicate via XAML binding only - the XrwXAML.ViewModelCore<MainView> class has been rejected from Xrw version 1.0 and there is no reference back from ViewModel to the View.

This demonstration application is the first one in the series of "Writing a XAML..." articles, that produces a meaningful result. Exactly because of that and because of the opportunity to add a lot of cool features henceforth, i think this article will become some updates in the foreseeable future, e.g.:

  • Detection whether assembly platform matches the running platform (Win32/x64/AnyCPU), because the assembly bust be loadable.
  • Correct dealing with operators (op_) and class creators (cctor).
  • Memorize application settings
  • ...

Focus

Since the previous nine articles "Writing a XAML ..." already demonstrated several MVVM techniques, this article shall provide not a general purpose sample but a useful tool utilizing XAML for X11 to

  • generate HTML help for .NET/MONO assemblies.

Using the code

The sample application was written with Mono Develop 2.4.1 for Mono 2.8.1 on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop. Neither the port to any older nor to any newer version should be a problem. The sample application's solution is build with MONO/.NET 3.5. It consists of two projects (the complete sources are provided for download):

  • XamlDocer contains the source code of the sample application.
  • XamlDocerTestAssembly contains the source code of a test assembly (starting with version 0.20)
  • XamlPreprocessor contains the source code of the XAML preprocessor.

The sample application is also tested with Mono Develop 3.0.6 for Mono 3.0.4 on OPEN SUSE 12.3 Linux 64 bit DE and GNOME desktop, IceWM, TWM und Xfce.

The only difference between the 32 bit and the 64 bit solution is the definition of some X11 specific data types, as already described in the Programming Xlib with Mono develop -Part 1: Low level (proof of concept) article.

The Xlib/X11 window handling is based on the X11Wrapper assembly version 1.0 (a library version 1.0 release candidate is included in this solution), that defines the function prototypes, structures and types for Xlib/X11 calls to the libX11.so. This assembly has been developed for the Programming Xlib with Mono Develop - Part 1: Low-level (proof of concept) project and has been advanced during the Programming the Roma Widget Set (C# X11) - a zero dependency GUI application framework - Basics project.

The GUI framework is based on the Xrw assembly version 1.0 (a library version 1.0 release candidate is included in this solution), that defines the widgets/gadgets and its wrapper classes used within the XAML code (that should be as near to the Microsoft® original as reasonable). This assembly has been developed during the Programming the Roma Widget Set (C# X11) - a zero dependency GUI application framework - Basics project.

 

Update with version 0.30

The X11Wrapper assembly is now an early preview of the upcomming version 1.1. Some X11 API wrapper have been added but no major changes have been made.

The Xrw assembly is now an early preview of the upcomming version 1.1. Some radical changes have been made:

  • The XrwXAML controls do no longer base on the Xrw widgets.
  • Every application window is based on only one X11 window, XrwXAML controls avoid to use X11 windows.
  • Rendering is based on Cairo now, instead of X11.
 

The sample application heavily utilizes reflection to determine the API prvided by the assembly that is to be documented and adds additional documentation from the assemblie's XML documentation file.

There is an excellent article Reflection in .NET by keesari_anjaiah here at code project, that introduces all the techniques used in this application.

The creation of the XML documentation file is a standard feature of MonoDevelop and Visual Studio and must be activated explicitely.

Image 7

To achieve the currently best possible results with the HTML documentation generator, assembly file and XML documentation file should be provided.

Platform independency

The next view images of the sample application show XamlDocer version 0.10 on several platforms.

Note: Later versions of the sample application might have a more advanced interface.

The first image shows the sample application on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop.

Image 8

The second image shows the sample application on OPEN SUSE 12.3 Linux 64 bit DE and Xfce.

Image 9

The third image shows the sample application on Windows® 10 64 Bit Edition.

Image 10

The application window utilizes the System.Windows.Controls.DockPanel as it's root layout manager. It has the children System.Windows.Controls.Menu (menu, dock: top), System.Windows.Controls.TextBlock (for output, dock: bottom) and System.Windows.Controls.Grid (for action area, dock: center).

There is no functional difference between the X11 and Windows® 10 versions of the sample application, they share the same XAML code and code behind.

Walk through

Main view file context

The XAML (MainWindow.xaml)

Here the complete code of the XAML file (X11 32 Bit MonoDevelop solution):

XML
<Window x:Class="XamlDocer.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:XamlDocer"
    mc:Ignorable="d"
    Title="Documentation processor" Height="350" Width="525">
  <Window.Resources>
    <local:MainWindowViewModel x:Key="MainViewModel" />
  </Window.Resources>
  <DockPanel Name="MainDock" DataContext="{StaticResource MainViewModel}">
    <Menu x:Name="menuMain" DockPanel.Dock="Top">
      <MenuItem x:Name="menuitemFile" Header="_File">
        <MenuItem x:Name="menuitemFileExit" Header="Exit"
                  Command="{Binding MenuitemFileExit_Command}" CommandParameter="null" >
          <MenuItem.Icon>
            <Image Source="Images/exit16.bmp"/>
          </MenuItem.Icon>
        </MenuItem>
      </MenuItem>
      <MenuItem x:Name="menuitemConfig" Header="_Config"></MenuItem>
      <MenuItem x:Name="menuitemHelp" Header="_?">
        <MenuItem x:Name="menuitemQmarkHelp" Header="Help"
                  Command="{Binding MenuitemQmarkHelp_Command}" CommandParameter="null" >
          <MenuItem.Icon>
            <Image Source="Images/quest16.bmp"/>
          </MenuItem.Icon>
        </MenuItem>
        <MenuItem x:Name="menuitemQmarkAbout" Header="About"
                  Command="{Binding MenuitemQmarkAbout_Command}" CommandParameter="null" >
          <MenuItem.Icon>
            <Image Source="Images/info16.bmp"/>
          </MenuItem.Icon>
        </MenuItem>
      </MenuItem>
    </Menu>
    <TextBlock Name="textblockStatus" DockPanel.Dock="Bottom" Height="18" Background="Silver"
               Text="{Binding StatusText}" />
    <Grid Name="gridActionArea" Background="#FFF0F0F0" >
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="6"/><!-- Left padding. -->
        <ColumnDefinition Width="3.0*"/>
        <ColumnDefinition Width="10"/><!-- Col 1-2 padding. -->
        <ColumnDefinition Width="1.0*"/>
        <ColumnDefinition Width="6"/><!-- Right padding. -->
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="4"/><!-- Row padding. -->
        <RowDefinition Height="24"/>
        <RowDefinition Height="8"/>
        <RowDefinition Height="24"/>
        <RowDefinition Height="16"/><!-- Row padding. -->
        <RowDefinition Height="24"/>
        <RowDefinition Height="8"/>
        <RowDefinition Height="24"/>
        <RowDefinition Height="16"/><!-- Row padding. -->
        <RowDefinition Height="24"/>
        <RowDefinition Height="8"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="4"/><!-- Row padding. -->
      </Grid.RowDefinitions>
      <Label x:Name="labelDllFile" Content="Assembly DLL file (mandatory):"
             Grid.Column="1" Grid.Row="1" />
      <Button Name="buttonDllFile" Grid.Row="1" Grid.Column="3" Content="..."
              Command="{Binding ActionareaDllFile_Command}" CommandParameter="null" ></Button>
      <TextBlock x:Name="textblockDllFile" Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="3"
              TextWrapping="NoWrap" Text="{Binding DllFilePath}" Background="#FFF6F6F6" />
      <Label x:Name="labelXmlFile" Content="Assembly XML file (optional):"
             Grid.Column="1" Grid.Row="5" />
      <Button Name="buttonXmlFile" Grid.Row="5" Grid.Column="3" Content="..."
              Command="{Binding ActionareaXmlFile_Command}" CommandParameter="null" ></Button>
      <TextBlock x:Name="textblockXmlFile" Grid.Column="1" Grid.Row="7" Grid.ColumnSpan="3"
                 TextWrapping="NoWrap" Text="{Binding XmlFilePath}" Background="#FFF6F6F6" />
      <Button Name="buttonCompile" Grid.Row="9" Grid.Column="3" Content="Compile" FontSize="14"
              FontWeight="Bold" Command="{Binding ActionareaCompile_Command}" CommandParameter="null"
              IsEnabled="{Binding EnableCompile}"></Button>
      <Label x:Name="labelCompile" Content="Compile results:" Grid.Column="1" Grid.Row="9" />
      <TextBlock Name="textboxCompile" Grid.Row="11" Grid.Column="1" Grid.ColumnSpan="3"
                 Background="#FFF6F6F6" Text="{Binding Output}" />
    </Grid>
  </DockPanel>
</Window>

All the interaction between GUI and code behind is realized via binding. The MenuItems and two Buttons use RelayCommand instances, the TextBlocks bind to String properties. The binding source is commonly defined as:

XML
<DockPanel Name="MainDock" DataContext="{StaticResource MainViewModel}">

Limitations of the XAML syntax

X11/Xrw implementation:

  • Currently the MenuItem doesn't compile the access qualifier (e.g.: <MenuItem x:Name="menuitemConfig" Header="_Config"></MenuItem>) if it has no child items (and therefore it displays e.g. _Config instead of Config).
  • The early preview of the upcomming Xrw assembly version 1.1 doesn't support menu items with icon.

The code behind (MainWindow.xaml.cs)

The corresponding C# code file of the main view is MainWindow.xaml.cs and it contains just the minimum code:

C#
using System;
using System.Diagnostics;

using X11;
using Xrw;
using XrwXAML;

// Replica
using Microsoft.Win32;
using System.Windows;
using System.Windows.Controls;

namespace XamlDocer
{
  public partial class MainWindow : XrwXAML.Window
  {

    /// <summary>The default constructor.</summary>
    public MainWindow ()
      : base (-1, -1)
    {
      InitializeComponent ();
    }

  }

}

Main view model file context

The MainWindowViewModel.cs file contains all "RelayCommands" connected to application menu items and buttons as well as all "String" properties connected to the text blocks. The complete source contains almost 2000 lines of code and comments. I will just pick and discuss some snippets...

First: The RelayCommands, that are bound to menu items and buttons.

C#
#region MenuItem relay properties

/// <summary>Provide the relay command for MenuitemFileExit.</summary>
public System.Windows.Input.ICommand MenuitemFileExit_Command
{ get { return _menuitemFileExit_Command; } }

/// <summary>Provide the relay command for MenuitemQmarkHelp.</summary>
public System.Windows.Input.ICommand MenuitemQmarkHelp_Command
{ get { return _menuitemQmarkHelp_Command; } }

/// <summary>Provide the relay command for MenuitemQmarkAbout.</summary>
public System.Windows.Input.ICommand MenuitemQmarkAbout_Command
{ get { return _menuitemQmarkAbout_Command; } }

#endregion MenuItem relay properties

#region ActionArea relay properties

/// <summary>Provide the relay command for ActionareaDllFile.</summary>
public System.Windows.Input.ICommand ActionareaDllFile_Command
{ get { return _actionareaDllFile_Command; } }

/// <summary>Provide the relay command for ActionareaXmlFile.</summary>
public System.Windows.Input.ICommand ActionareaXmlFile_Command
{ get { return _actionareaXmlFile_Command; } }

/// <summary>Provide the relay command for ActionareaCompile.</summary>
public System.Windows.Input.ICommand ActionareaCompile_Command
{ get { return _actionareaCompile_Command; } }

#endregion ActionArea relay properties               

Second: The properties, that are bound to text blocks.

C#
#region View bindable properties

/// <summary>Get or set the path of the DLL file to compile XML documentation from.</summary>
/// <value>The path of the DLL file to compile XML documentation from.</value>
/// <remarks>Since the MVVM ViewModel doesn't know about the view -
/// view interaction is realized via binding.</remarks>
public string DllFilePath
{   get    {    return _dllFile;        }
    set    {    _dllFile = value;        OnPropertyChanged("DllFilePath");    }
}

/// <summary>Get or set the path of the XML file to compile XML documentation from.</summary>
/// <value>The path of the XML file to compile XML documentation from.</value>
/// <remarks>Since the MVVM ViewModel doesn't know about the view -
/// view interaction is realized via binding.</remarks>
public string XmlFilePath
{   get    {    return _xmlFile;        }
    set    {    _xmlFile = value;        OnPropertyChanged("XmlFilePath");    }
}

/// <summary>Get or set the flag defining whether all prereqisits to compile are met.</summary>
/// <value>The flag defining whether all prereqisits to compile are met.</value>
/// <remarks>Since the MVVM ViewModel doesn't know about the view -
/// view interaction is realized via binding.</remarks>
public bool EnableCompile
{   get    {    return _enableCompile;    }
    set    {    _enableCompile = value;    OnPropertyChanged("EnableCompile");    }
}

/// <summary>Get or set the log output.</summary>
/// <value>The log output.</value>
/// <remarks>Since the MVVM ViewModel doesn't know about the view -
/// view interaction is realized via binding.</remarks>
public string Output
{   get    {    return _output;        }
    set    {    _output = value;            OnPropertyChanged("Output");    }
}

/// <summary>Get or set the status bar text.</summary>
/// <value>The status bar text.</value>
/// <remarks>Since the MVVM ViewModel doesn't know about the view -
/// view interaction is realized via binding.</remarks>
public string StatusText
{   get    {    return _statusText;        }
    set    {    _statusText = value;        OnPropertyChanged("StatusText");    }
}

#endregion View bindable roperties

Third: The INotifyPropertyChanged implementation of MainWindowViewModel.

C#
#region INotifyPropertyChanged Members

/// <summary>Notify listeners about property value change.</summary>
/// <param name="propertyName">The <see cref="System.String"/> name
/// of the value changed property.</param>
private void OnPropertyChanged(string propertyName)
{
   if (PropertyChanged != null)
   {
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
}

#endregion INotifyPropertyChanged Members

The creation of HTML documentation is realized in three phases:

  1. Read the members from the assembly DLL file.
  2. Read additional member information from the assemblie's XML documentation file.
  3. Write HTML documentation files.

To store the member information meanwhile, the DocerTree class is used. It is implemented as a singleton and can hold any type of DocerNode to build up a tree structure, but in fact the root nodes are of type DocerNodeType.Assembly.

The first phase - read the members from the assembly DLL file - initially creates a DocerNode of type DocerNodeType.Assembly and adds all the members, found in the assembly DLL file, to this DocerNode's list of children. Typically the first generation of children are DocerNodes of type DocerNodeType.Namespace. These DocerNodes contain in turn the second generation of children, typically of type DocerNodeType.Namespace or type DocerNodeType.Type. DocerNodes of type DocerNodeType.Namespace can always have children of the next generation. DocerNodes of type DocerNodeType.Type are always leafs of the tree structure and represent classes, enumerations and so on including their fields, constructors, properties, methods and so on.

Fourth: Read the members from the assembly DLL file.

C#
/// <summary>Read the members from the library DLL file into
/// one <see cref="OpfDocer.DocerTree"/> instance.</summary>
/// <param name="assembly">The XML node, that contains the members to read.</param>
private void ReadMembers(Assembly assembly)
{
  DocerTree dt = DocerTree.Instance;

  if (assembly == null)
    return;
 
  try
  {
    DocerNode dnAssembly = dt.FindOrCreateAssemblyDocerNode (assembly.ManifestModule.Name);
    if (dnAssembly != null)
    {
      StatusText = "Read assembly file '" + DllFilePath + "' for type details.";
      foreach(Type type in assembly.GetTypes())
      {   
        if (!type.FullName.Contains ("PrivateImplementationDetails") &&
            !type.FullName.Contains ("$ArrayType$"))
        {
          string beautifiedName = type.FullName.Replace("+", ".");
          beautifiedName = DocerNode.ToDisplayFriendlyName (beautifiedName).Replace("System.", "");
          
          DocerNode dn = dnAssembly.FindOrCreateTypeDocerNode (beautifiedName);
          if (dn != null)
          {
            // Store it...
            
            string interfaces = "";
            foreach (Type interfaceType in type.GetInterfaces())
            {
              if (interfaces == "")
                interfaces += interfaceType.Name;
              else
                interfaces += ", " + interfaceType.Name;
            }
            dn.Interfaces = DocerNode.ToDisplayFriendlyName (interfaces);
              
            foreach (FieldInfo fieldInfo in type.GetFields (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
            {
              // Store it...
            }
            foreach (FieldInfo fieldInfo in type.GetFields (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
              // Store it...
            }
            dn.FieldMember.Sort (delegate(TypeMemberDocerNode d1, TypeMemberDocerNode d2)
            {  return d1.Name.CompareTo(d2.Name);  });
            
            foreach (PropertyInfo propertyInfo in type.GetProperties(
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
            {
              // Store it...
            }
            foreach (PropertyInfo propertyInfo in type.GetProperties(
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
              // Store it...
            }
            dn.PropertyMember.Sort (delegate(TypeMemberDocerNode d1, TypeMemberDocerNode d2)
                {  return d1.Name.CompareTo(d2.Name);  });
            
            foreach (ConstructorInfo constructorInfo in type.GetConstructors(
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
            {
              // Store it...
            }
            foreach (ConstructorInfo constructorInfo in type.GetConstructors(
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
              // Store it...
            }
            dn.MethodMember.Sort (delegate(TypeMemberDocerNode d1, TypeMemberDocerNode d2)
                {  return d1.Name.CompareTo(d2.Name);  });
            
            foreach (MethodInfo methodInfo in type.GetMethods (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
            {
              // Store it...
            }
            foreach (MethodInfo methodInfo in type.GetMethods (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
              if (methodInfo.Name.StartsWith ("get_") || methodInfo.Name.StartsWith ("set_"))
                continue;
              
              // Store it...
            }
            dn.MethodMember.Sort (delegate(TypeMemberDocerNode d1, TypeMemberDocerNode d2)
                {  return d1.Name.CompareTo(d2.Name);  });
            
            foreach (EventInfo eventInfo in type.GetEvents (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
            {
              // Store it...
            }
            foreach (EventInfo eventInfo in type.GetEvents (
                         BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
              // Store it...
            }
            dn.EventMember.Sort (delegate(TypeMemberDocerNode d1, TypeMemberDocerNode d2)
                {  return d1.Name.CompareTo(d2.Name);  });
          }
        }
      }
    }
  }
  catch (Exception ex)
  {
    if (!string.IsNullOrEmpty (Output))
      Output += "\n" + "ERROR " + ex.Message + "\n" + ex.StackTrace;
    else
      Output = "ERROR " + ex.Message + "\n" + ex.StackTrace;
    Console.WriteLine (ex.Message + "\n" + ex.StackTrace);
  }
}

The second phase - read additional member information from the assemblie's XML documentation file - doesn't create any new DocerNode. It just searches the tree structure for the matching node and adds member information to it. These XML comments are evaluated:

  • For a type (enumeration, class, ...): "code", "example", "summary", "remarks".
  • For a type's field: "code", "example", "summary", "remarks"
  • For a type's property: "code", "example", "exception", "summary", "remarks", "value"
  • For a type's method: "code", "example", "exception", "param", "summary", "remarks", "returns"

The third phase - write HTML documentation files - creates the folders /images and /members and writes the files.

 

Update with version 0.30

Project settings (to store strings, images, ... on behalf of the application's current user or the application/all application users) are specific to Visual Studio. The next image shows the empty project settings page.

   Image 11

To provide a platform independent implementation, the application needs a similar functionality for Mono Develop too. In order to achive this, the SystemSettings class is provided.

The SystemSettings class is used to store the actual settings immediately a setting changes and to restore the last recent settings during application start.

The SystemSettings class utilizes the SystemFolder class to access user's private property path and application's global property path.

 

Usage

The XamlDocer sample application download links on the top of the page support:

  • X11_32 - Application compilation target and assembly file to create XML documentation must be: Unix/Linux 32 bit
  • X11_64 - Application compilation target and assembly file to create XML documentation must be: Unix/Linux 64 bit
  • Win10 - Application compilation target and assembly file to create XML documentation must be: Windows Win32, x64 and AnyCPU, determined by the selected target platform (compilation for x64 already included).

Using the XamlDocer application to create HTML help

  1. Prepare a working folder.
  2. Copy assembly file and XML documentation file into the folder.
  3. Ensure you have compiled/choosen XamlDocer for the right platform x32/x64/AnyCPU (since XamlDocer loads the assembly file - to create HTML documentation for - into memory, the platforms must match).
  4. Start XamlDocer application and select the assembly file (the XML documentation file will be recognized automatically).
  5. Optionally select the XML documentation file, if not recognized automatically.
  6. Apply the settings (starting with version 0.20, there are settings to include/exclude non-public types/properties/methods/fields/events).
  7. Run the creation of HTML documentation.

The next image shows the current version of XamlDocer.

Image 12


  4.

  5.

  6.


  7.

 









 

 

Update with version 0.30

The show/hide object inherited member property button is activated now.

 

The next image shows a sample folder, that contains the supplied assembly file and XML documentation file (X11Wrapper.dll and X11Wrapper.xml) as well as the resulting HTML documentation (_index.html, /members and /images) on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop.

Image 13

 

The result (started with the _index.html file) of the HTML documentation creation for X11wrapper.dll and X11wrapper.xml looks like that:

Image 14

HTML documentation language

Microsoft's XML Documentation language description is devided into multiple short articles, that explain the serveral aspects very technical. In addition to that i highly recommend Michael D Elliott's excellent illustrated article C# and XML Source Code Documentation here at code project.

I want to mention some aspechts nevertheless:

  • XamlDocer supports namespace documentation just like NDoc and Sandcastle do: By adding a commented internal class NamespaceDoc {} to the namespace. I do typically use the /// <summary></summary> and /// <remarks></remarks> tags on this class.
  • I do typically comment utilizing the <see cref=""/> and <c></c> tags. (The <see cref=""/> tag is completed automatically, if <see> is typed by hand. The <c></c> tag is short enough to be completely typed by hand.) For Mono Develop projects it's a good practice to include the namespaces of all classes, that are used as parameter or return value, and to reference the classes without namespace. E. g,:
C#
using System.Windows;

...

// <param name="hitTest">The <see cref="Point"/> for the hit test.</param>

The result looks like:       Param: hitTest           The System.Windows.Point for the hit test.

  • I do typically comment parameter and return value according to this scheme:
C#
<code>/// <returns>Returns <see cref="Boolean"/> <c>true</c> if the top-level
/// header has to open it's sub-menu on mouse enter.</returns></code>

The result looks like:       Return                       Returns System.Boolean true if the top-level ...

HTML documentation theme

Currently there is only one target theme, HTML documents are written to. It provides (different to Microsoft's standard) all members of one type inside one single HTML file (page). This is more compact, but it might write the same things multiple times, e.g. if a member is described for the base class and all it's deived classes.

The curent target theme creates the HTML documentation chapters Type title, Type summary, Namespace, Assembly, Inheritance tree, Interfaces and Constructors like that ...

Image 15

The constructor's parameters are part of the file - there is no need to follow a link to get the complete set of information.

The curent target theme creates the HTML documentation chapters Properties and Methods like that ...

Image 16

The methos's parameters and return values are part of the file - there is no need to follow a link to get the complete set of information.

The curent target theme creates the HTML documentation chapters Fields, Events, Remarks and Exampless like that ...

Image 17

Fixed errors

Fixed with version 0.2:

  • The 'Inheritance Hierarchy' section didn't show the inheritance hierarchy but the containment hierarchy.
  • The links to superordinated/subordinated types have been broken. The '.html' extension was missing.
  • Type member accessibility (public/non-public) has been 'guessed' but is now determined via the BindingFlags correctly.
  • Type member (constructors and methods) provided links to detail pages, even if detail pages have not been written.

Fixed with version 0.3:

  • Links within the generated help, that include a thumbnail image, suppress the image border now.
  • The show/hide non-public types property bug is fixed now. It had no effect.

Improvements

Improved with version 0.2:

  • Switch documentation for non-public types and type members (properties, methods, fields and events) on/off.

Improved with version 0.3:

  • Application memorizes the last selection and restores it after a restart.
  • The show/hide object inherited member property button is activated now.

Planned

  • [realized] Application memorizes the last selection and restores it after a restart.
  • Alternative icon images support.
  • Include of non-generated pages.

Points of Interest

This is another XAML application for X11, fully compatible with Microsoft®, showing the main advantages of this approach (compared to an implementation with GTK+ or KDE): The 100% cross platform compatible GUI definition and the savings of code lines to create the GUI.

I hope you enjoy this early stage of HTML documentation generator and i hope, even if it's far from a release state,

  • it might be helpful for you (adjusting and completing the XML comments to get an excellent documentation in the future),
  • it makes you curious about the next step(s) and
  • it inspires you to give feedback.

History

The first version of this article is from 17. March 2017.

The second version of this article is from 24. March 2017.

The third version of this article is from 18. June 2017.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Celonis SA
Germany Germany
I am currently the CEO of Symbioworld GmbH and as such responsible for personnel management, information security, data protection and certifications. Furthermore, as a senior programmer, I am responsible for the automatic layout engine, the simulation (Activity Based Costing), the automatic creation of Word/RTF reports and the data transformation in complex migration projects.

The main focus of my work as a programmer is the development of Microsoft Azure Services using C# and Visual Studio.

Privately, I am interested in C++ and Linux in addition to C#. I like the approach of open source software and like to support OSS with own contributions.

Comments and Discussions

 
GeneralMy vote of 5 Pin
MathildePichard26-Mar-17 1:39
MathildePichard26-Mar-17 1:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.