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.