views:

27

answers:

2

What is the best way to document a dependency property?

Should I put the xml documentation on the field:

/// <summary>Documentation goes here</summary>
public static readonly DependencyProperty NameProperty = 
        DependencyProperty.Register(...)

or on the property:

/// <summary>and/or here?</summary>
public string Name{ get{...} set{...} }

or do I really need to document (and maintain) both?

A: 

You should document and maintain both. One is the dependency property, the other is a regular property that just happens to be implemented as accessing that dependency property. They are not the same thing and require separate documentation.

Jeff Yates
Well, sure there is a technical difference. But I don't see how the documentation will be all that different. Basically both need to describe the meaning of the value. Other than that its just api difference.
Lawnmower
That's not true. The implementation of the instance property is somewhat irrelevant. A caller should never be relying on implementation. You should take a cue from Microsoft who quite clearly see it as necessary to document both items. After all, a user of one should not need to know that they have to look at the other for information. Assuming the two are linked is prone to making the incorrect assumption.
Jeff Yates
Microsoft's documentation of property fields is really poor. Its 'Identifies the [name of property] dependency property.' That's what everybody can see on first sight from the declaration it self. That's completely useless (probably even autogenerated). It should document the meaning of the property. And to the other point: The implementation of the property is relevant! For one thing, WPF assumes that the property is directly backed by the dp, since it bypasses the property and accesses the dp directly.
Lawnmower
"After all, a user of one should not need to know that they have to look at the other for information. Assuming the two are linked is prone to making the incorrect assumption." I totally agree with you here. Now have a look at how microsoft documents the DPs! In order to find out what that thing is for, you have to find the corresponding c# property and read that documentation.
Lawnmower
A: 

Ok, this is what I've come up with.

I use a special xml tag at the dependency properties that will be replaced by an xsl transformation. It would be possible to do it without it, but then Visual Studio issues a warning because the field appears undocumented.

/// <dpdoc />
public static readonly DependencyProperty PositionProperty = 
    DependencyProperty.Register(...)

The C# property is documented as usual, just make sure not to forget the value description.

/// <summary>Gets or sets the position of this element</summary>
/// <value>Position (in pixel) relative to the parent's upper left corner.</value>
/// <remarks><para>
/// If either the <c>x</c> or <c>y</c> component is <c>+inf</c> this indicates...
/// </para></remarks>
public Point Position{ get{...} set{...} }

Visual studio creates an xml file from those comments during building. With a little xsl transformation the dpdoc node is replaced by a modified version of the property documentation. The resulting xml file is the same as if we nicely documented the property identifier. It even includes a short note that there is an alternative way of accessing the variable:

/// <summary>Position (in pixel) relative to the parent's upper left corner.</summary>
/// <remarks><para>
/// If either the <c>x</c> or <c>y</c> component is <c>+inf</c> this indicates...
/// <para>
/// This dependency property can be accessed via the <see cref="Position"/> property.
/// </para>
/// </para></remarks>
public static readonly DependencyProperty PositionProperty = 
    DependencyProperty.Register(...)

That way, both API's have proper documentation and we don't need to duplicate the documentation in the code. The xsl transformation can be done in the post-build events or be integrated in the documentation generation process.

Here's the xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="//dpdoc">
        <xsl:variable name="propertyName" select="concat('P:', substring(../@name,3,string-length(../@name)-10))" />
        <summary>
            <xsl:apply-templates select="//member[@name=$propertyName]/value/node()"/>
        </summary>
        <xsl:apply-templates select="//member[@name=$propertyName]/*[not(self::remarks)][not(self::summary)][not(self::value)]"/>
        <remarks>
            <xsl:apply-templates select="//member[@name=$propertyName]/remarks/node()"/>
            <para>
                This dependency property can be accessed via the
                <see>
                    <xsl:attribute name="cref"><xsl:value-of select="$propertyName"/></xsl:attribute>
                </see>
                property.
            </para>
        </remarks>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Why I want to have it that way:

  • Both the property identifier (the DependencyProperty instance) and the property, are public and can therefore legally be used to access the property. Thous we have two APIs to the same logical variable.
  • Code documentation should describe what is not already there to see. In this context it should describe the meaning of the property and its value and how to use it correctly. Since both, property identifier and the c# property, reference the same logical variable, they have the same meaning.
  • The user can freely choose one of the two ways to access the logical variable, and musn't be aware of the other. Thous both must be documented properly.
  • Copy-pasting code comments is just as bad as copy-pasting code.
Lawnmower