This project has moved and is read-only. For the latest updates, please go here.

API Filter Member Selection Problem

Topics: User Forum
Aug 22, 2009 at 3:33 AM

When selecting individual members of a class for inclusion, the tickmark for the class is set or unset depending on whether more or less than half the members have been selected.  This is stated as being 'for efficiency', but it has an undesired side effect.

If more than half the members are ticked and the class itself is therefore ticked, a number of members that are not listed for the class (and, therefore obviously are not ticked) become included in the build.  Specifically, for a VB project the 'hidden' delegates for the class events are documented. 

There is no point in documenting the delegates, as all necessary information is included in the comments for the events themsleves. Because the delegates are 'hidden' they have no comments, and generate a missing comments warning. The delegates are listed in the API filter at the Namespace level , but whether they are ticked or unticked in the tree makes no difference.

Making the event delegates explicit and then using the Exclude tag does not change Help File builder action at all - the delegates are still listed at the namespace level in the API filter and included in the documentation whether they are ticked or not.  I had hoped that using the Exclude tag might mean that entries for the delegates appeared in the tree at the class level and I could untick them (this is what the XML documentation guide implies should have happened).

Is there any way to select more than half the class members in the API filter without setting the selection tick for the whole class, and therefore including these unwanted members in the documentation?

Aug 22, 2009 at 9:01 PM

VB tends to add internal members for certain items.  Unfortunately, you don't have control over that.  Mostly, they are private and won't show up unless you are include private/internal members.  If you can create an example that demonstrates the problem, I'll take a look at it.



Aug 23, 2009 at 6:59 AM

I suspect that the problem is more to do with the level at which the event delegates are documented, rather than whether they are 'hidden' or not.

For the attached example, note that one of the event handlers is defined explicitly, and the other is implicit. 

Build the project, then create the documentation with all options left at their defaults.

The two event handler delegates are doumented at the Namespace level in the default build.  Use API filter to deselect the delegates and rebuild - they are still included in the documentation.  Use the API filter to uncheck everything in the Class, and then re-select just enough class members (Including the events) so that the class selection box does not get automatically ticked (ie, less than half the members) and build again - the delegates are not included.

Whether the delegates are explicit or implicit has not affected their inclusion, nor has whether or not they are ticked in the API filter (where they are listed at the namespace level), but the way that the _class_ members are selected in the API filter has had an effect, even though the delegates are not listed at this level.

Imports System.ComponentModel
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Windows.Forms

Namespace Sample
    ''' <summary>
    ''' Clas Library Sample Control
    ''' </summary>
    ''' <remarks>A graphical control that demonstrates how the documentation of the event handler
    ''' delegates changes according to how the members are selected in the API filter.
    ''' </remarks>
    <System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
    Class NamespaceDoc
    End Class
    Public Class Sample : Inherits System.Windows.Forms.Control
        Implements INotifyPropertyChanged

        ''' <summary>Required designer variable.</summary>
        ''' <remarks>The control will raise a PropertyChanged event for a change to any property.</remarks>
        Private components As System.ComponentModel.Container = Nothing

        ''' <summary>Occurs when a property of the control has changed.</summary>
        ''' <param name="sender">The instance of the control that generated the event</param>
        ''' <param name="e">A <see cref="PropertyChangedEventArgs"/> class instance</param>
        ''' <remarks>The control will raise a PropertyChanged event for a change to any property.
        ''' </remarks>
        Public Event PropertyChanged As PropertyChangedEventHandler _
            Implements INotifyPropertyChanged.PropertyChanged

        Private Sub NotifyPropertyChanged(ByVal info As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
        End Sub

        ''' <summary>The explicit handler for the WidthChangeEvent</summary>
        ''' <param name="sender">The object that raised the event</param>
        ''' <param name="e">An EventArgs object that refers to the event</param>
        ''' <remarks>This delegate is documented at the Class level.</remarks>
        Delegate Sub WidthChangeEventHandler(ByVal sender As Object, ByVal e As System.EventArgs)

        ''' <summary>The WidthChange event.</summary>
        ''' <remarks>This event is raised whenever the width changes.</remarks>
        Public Event WidthChange As WidthChangeEventHandler

        ''' <summary>The LengthChange event (handler is implied)</summary>
        ''' <param name="sender">The object that raised the event</param>
        ''' <param name="e">An eventargs object that refers to the event</param>
        ''' <remarks>This event is raised whenever the length changes</remarks>
        Public Event LengthChange(ByVal sender As Object, ByVal e As System.EventArgs)

        Private myWide As Single               'internal variable for Width
        Private myLength As Single             'internal variable for Length
        Private Shorter As Single              'internal variable for control size

        ''' <summary>Constructor for the Sample class.</summary>
        ''' <remarks>The constructor takes no arguments. An instance of Sample is returned, with the
        ''' instance properties set to the default values.</remarks>
        Public Sub New()
            ' This call is required by the Windows.Forms Form Designer.

            Me.myWide = 10.0!
            Me.myLength = 100.0!
            PointerPen = New Pen(Color.Black, myWide)

        End Sub

        ''' <summary>Clean up any resources being used.</summary>
        ''' <param name="disposing"></param>
        ''' <remarks></remarks>
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not components Is Nothing Then
                End If
            End If
        End Sub
        ''' <summary>A value which defines the Width of the graphic.</summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>Default is 10.</remarks>
        <Category("Behavior"), _
                Description("Wideness of the graphic (in pixels)"), _
                DefaultValue(10.0!), _
                Browsable(True)> _
                Public Property Wide() As Single
                Return myWide
            End Get
            Set(ByVal Value As Single)
                If myWide <> Value Then
                    myWide = Value
                    PointerPen.Width = myWide
                End If
            End Set
        End Property
        ''' <summary>A value which defines the Length of the graphic.</summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>Default is 100.</remarks>
        <Category("Behavior"), _
        Description("Proportion of the control width for which the graphic is drawn"), _
        DefaultValue(100.0!), _
        Browsable(True)> _
        Public Property Length() As Single
                Return myLength
            End Get
            Set(ByVal Value As Single)
                If Value = 0 Then
                    Exit Property
                End If
                If myLength <> Value Then
                    myLength = Value
                End If
            End Set
        End Property

#Region "Component Designer generated code"
        ''' <summary>
        ''' Required method for Designer support - do not modify
        ''' the contents of this method with the code editor.
        ''' </summary>
        Private Sub InitializeComponent()

        End Sub
#End Region

        Private buffer As Bitmap
        Private PointerPen As Pen
        ''' <summary>Refreshes the display</summary>
        ''' <remarks>Overridden in the derived control to perform layout of the graphical components.</remarks>
        Public Overrides Sub Refresh()

            Shorter = Me.Width
            If Me.Height < Shorter Then Shorter = Me.Height
            If Shorter = 0 Then Exit Sub

            buffer = New Bitmap(Shorter, Shorter, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
            Dim g As Graphics = Graphics.FromImage(buffer)

            g.PixelOffsetMode = PixelOffsetMode.Half
            g.SmoothingMode = SmoothingMode.AntiAlias

            Dim gP As GraphicsPath = New GraphicsPath
            gP.AddEllipse(0, 0, Shorter, Shorter)
            Dim REG As Region = New Region(gP)
            Me.Region = REG

        End Sub
        ''' <summary>Raises the Paint event.</summary>
        ''' <param name="e">An EventArgs that contains the event data.</param>
        ''' <remarks>Performs the painting of the gauge control</remarks>
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            Dim G As Graphics = e.Graphics

            Dim t0 As Single, t1 As Single, t2 As Single
            If buffer Is Nothing Then Exit Sub

            'Paint the control
            G.DrawImage(buffer, 0, 0)
            t0 = Shorter * myLength / 100
            t1 = (Shorter - t0) / 2
            t2 = Shorter / 2
            G.DrawLine(PointerPen, New Point(t1, t2), New Point(t0 + t1, t2))

        End Sub

        Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        End Sub

    End Class
End Namespace


Aug 25, 2009 at 10:46 PM

The workaround is to turn 'Document Private Fields' to True, then in the API filter to un-tick all the private fields.   As there is at least one private field for every public one, that will bring the number of ticked fields below half, the class selection box will un-tick itself, and the build will not include the unwanted event handlers.

The drawback is that any public fields that later get added have to be ticked in the API filter before they get included in the build.