Silverlight DynamicResource Markup Extension

This will be my first post on Silverlight!

WPF offers two markup extensions, StaticResource and DynamicResource, that can be used to set property values from items in resource dictionaries.

The difference between the two can be summarized as:

  • StaticResource is evaluated at the start of the application, and will find resources defined before its actual usage;
  • DynamicResource is evaluated at a later point, and will find resources declared anywhere, before or after its usage.

Unfortunately, Silverlight does not include DynamicResource, but it is relatively easy to achieve something like that; that is the purpose of this post.

Check out the following code:

public class DynamicResource : MarkupExtension
{
    public DynamicResource()
    {
    }
 
    public String ResourceName { get; set; }
 
    public override Object ProvideValue(IServiceProvider serviceProvider)
    {
        var provideValueTarget = serviceProvider.GetService<IProvideValueTarget>();
        var target = provideValueTarget.TargetObject as FrameworkElement;
        var property = provideValueTarget.TargetProperty as PropertyInfo;
 
        if (target != null)
        {
            RoutedEventHandler handler = null;
            handler = (sender, e) =>
            {
                var elm = sender as FrameworkElement;
 
                if (elm != null)
                {
                    var resource = TryFindResource(elm, this.ResourceName);
                    var typeConverterAttribute = property.GetCustomAttributes(typeof(TypeConverterAttribute), true).OfType<TypeConverterAttribute>().SingleOrDefault() ?? property.PropertyType.GetCustomAttributes(typeof(TypeConverterAttribute), true).OfType<TypeConverterAttribute>().SingleOrDefault();
 
                    if (typeConverterAttribute != null)
                    {
                        var typeConverterType = Type.GetType(typeConverterAttribute.ConverterTypeName, false);
 
                        if (typeConverterType != null)
                        {
                            var typeConverter = Activator.CreateInstance(typeConverterType) as TypeConverter;
 
                            if (typeConverter != null)
                            {
                                resource = typeConverter.ConvertFrom(resource);
                            }
                        }
                    }
 
                    property.SetValue(sender, resource, null);
                }
 
                target.Loaded -= handler;
            };
 
            target.Loaded += handler;
        }
 
        return (property.PropertyType.IsClass == true) ? null : Activator.CreateInstance(property.PropertyType);
    }
 
    private static Object TryFindResource(FrameworkElement element, Object resourceKey)
    {
        var currentElement = element;
 
        while (currentElement != null)
        {
            var resource = currentElement.Resources[resourceKey];
            if (resource != null)
            {
                return resource;
            }
 
            currentElement = currentElement.Parent as FrameworkElement;
        }
 
        return Application.Current.Resources[resourceKey];
    }
}

I won't go into details on markup extensions and all that, but basically, this one hooks to the Loaded event of the FrameworkElement, thus deferring the setting of the property. The property and the target are found through the IProvideValueTarget instance and the resource is looked up recursively from the target element up to the Application instance. If the property to be set, or its class, defines a type converter, it will try to convert the found resource to the proper type.  In the meantime, it just returns the default value of the property type, null or a default instance, in case of a value type.

                             

No Comments

Add a Comment

As it will appear on the website

Not displayed

Your website