Silverlight Method Data Source Markup Extension

A quick way to obtain a data source from a method through a markup extension, without any code:

<ComboBox ItemsSource="{my:MethodDataSource MethodName=GetItems}"/>

Implementation is simple:

public class MethodDataSourceExtension : DependencyObject, IMarkupExtension<Object>

{

    public static readonly DependencyProperty TargetProperty = DependencyProperty.Register("Target", typeof(Object), typeof(MethodDataSourceExtension), new PropertyMetadata(null));

    public static readonly DependencyProperty ArgumentProperty = DependencyProperty.Register("Argument", typeof(Object), typeof(MethodDataSourceExtension), new PropertyMetadata(null));


    public String MethodName { get; set; }


    public Object Target

    {

        get { return this.GetValue(TargetProperty); }

        set { this.SetValue(TargetProperty, value); }

    }


    public Object Argument

    {

        get { return this.GetValue(ArgumentProperty); }

        set { this.SetValue(ArgumentProperty, value); }

    }


    public Object ProvideValue(IServiceProvider serviceProvider)

    {

        var rootObjectProvider = serviceProvider.GetService<IRootObjectProvider>();

        var target = (this.Target ?? rootObjectProvider.RootObject);

        var method = target.GetType().GetMethod(this.MethodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);

        var args = (this.Argument != null) ? new Object[] { this.Argument } : null;


        return method.Invoke((method.IsStatic == true) ? null : target, args);

    }

}

The MethodDataSourceExtension has three properties:

  • MethodName: the name of a method;
  • Target: the optional element from which the data source method will be retrieved; if not specified, the containing control (Page, UserControl, etc) will be used;
  • Argument: an optional argument to the data source method.

Because we might want to use bindings, the MethodDataSourceExtension class inherits from DependencyObject. This allows us to have:

<ComboBox ItemsSource="{my:MethodDataSource MethodName=GetItems, Target={Binding ElementName=SomeControl}}"/>

We can call any method, static or instance, as long as it is public. It can have a single parameter or no parameter at all.

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *