ContentPropertyAttribute

February 9th, 2009 by jason Leave a reply »

While diving into the programming of custom controls in Silverlight I wanted to set one of my properties as the “default property” from XAML.  What I mean here is that I wanted to emulate the behavior of many out-of-the-box controls in Silverlight (and WPF for that matter) where a property need not be explicitly specified, in all cases a content property of some sort.  For example, the Button control has a Content property which can be set in these three ways (excluding binding):

  1. <Button Content=”Click Me”/>
  2. <Button><Button.Content>Click Me</Button.Content></Button>
  3. <Button>Click Me</Button>

The relationship between these different ways of setting Button.Content should be fairly obvious.  Through XAML one can usually set any property on the underlying object via an attribute or child element.  Additionally, one property can be marked as the “default property”.  But how is this done?  How can I write a control and mark one of the properties as the “default property”.

In XAML/Silverlight/WPF parlance, this is refered to as the Content Property, which is confusing since there is also a property on a number of controls called content, and to make it even more confusing the property named Content is also the Content Property.  Confused?  Lets take a swing at this using my custom control and see how to set the Content Property on a control with no property called Content.

I have a control that doesn’t have “content” per se, but accepts a list of rules which regulate how the control should act.  I want the XAML to accept this list as the “default property”.  I want to be able to write:

<RuleManager>
  <Rule ... />
  <Rule ... />
  <Rule ... />
</RuleManager>

instead of the more verbose:

<RuleManager>
  <RuleManager.Rules>
    <Rule ... />
    <Rule ... />
    <Rule ... />
  </RuleManager.Rules>
</RuleManager>

The way I do this is with the ContentProperty Attribute in System.Windows.Markup:

[ContentPropertyAttribute("Rules")]
public class RuleManager
{

  public static readonly DependencyProperty RulesProperty =
    DependencyProperty.Register("Rules",
                                typeof(RulesCollection),
                                typeof(RuleManager),
                                new PropertyMetadata(null));

  public RulesCollection Rules
  {
    get { return (RulesCollection)GetValue(RulesProperty); }
    private set { SetValue(RulesProperty, value); }
  }

  public RuleManager()
  {
    Rules = new RulesCollection();
  }
}

The ContentPropertyAttribute class should probably be renamed something like DefaultXamlPropertyAttribute since it does not always specify Content, but does specify the default property.  Its constructor takes the name of the property to use as the default (or “content”) property. It took some digging, but this is the correct way to do it and it is tested working.  From XAML I need not specify the Rules element (aka property); the XAML parse will assume that information included here is mean for the Rules property based on the attribute.

MSDN documentation of ContentPropertyAtrtibute in Core CLR (Silverlight)

No TweetBacks yet. (Be the first to Tweet this post)
Advertisement

Leave a Reply

You must be logged in to post a comment.