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?
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:
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.