Working on a very simple DataForm control for Winforms I had the need to pass a function delegate to an attribute that qualifies a property to generate a ComboBox on the UI. The function was mean to be used as a way to retrieve the set of values you use to populate the Items property of the ComboBox.

I quickly discovered that I cannot pass that delegate as a parameter using the standard attribute qualifying syntax because: an attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

A quick and dirty workaround was to add a Dictionary<String, Func<IEnumerable>> to my DataForm control and a function to actually ‘register’ the delegate you want to use to populate the combox. The delegate is registered using a string key that you will later on pass to the attribute that qualifies the property.

Here are some code snippets taken from the DataForm:

...
private readonly Dictionary<string, Func<IEnumerable>> _loadItemsFunctions = new Dictionary<string, Func<IEnumerable>>();

/// <summary>
/// Registers the load item function, if a function exists with the same key
/// it gets overwritten.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="deleg">The deleg.</param>
public void RegisterLoadItemFunc(string key, Func<IEnumerable> deleg)
{
	_loadItemsFunctions[key] = deleg;
}
...

and the attribute class:

[AttributeUsage(AttributeTargets.Property)]
public class UiHintComboBoxAttribute : Attribute
{
	public UiHintComboBoxAttribute()
	{
		DropDownStyle = ComboBoxStyle.DropDownList;
		BindType = BindTo.SelectedValue;
	}

	/// <summary>
	/// Gets or sets the load items function, it's a string placeholder for a 
	/// function registered in the instance of the control that will use it.
	/// </summary>
	/// <value>The load items func.</value>
	public string LoadItemsFunc { get; set; }

	public string DisplayMember { get; set; }

	public string ValueMember { get; set; }

	public ComboBoxStyle DropDownStyle { get; set; }

	public BindTo BindType { get; set; }

	public enum BindTo
	{
		SelectedValue,
		SelectedItem
	}
}

A similar technique can be used if you need to pass descriptive strings along with your attributes and you need to localize those strings: you pass in a reference to a dictionary you populate with phrases in the correct language.

Related Content