Tag Archives: Silverlight

Custom Markup Extension To Replace IValueConverter

Something that’s been around in WPF for a long time but is just seeing the light of day in the upcoming Silverlight 5 release is the concept of a custom MarkupExtension.  For those unfamiliar with the concept, a MarkupExtension is anything within the curly braces “{}” of your xaml.

Some examples include, Binding, Static- and DynamicResource, Type, Static, etc.  You can look at the code below and see some examples:

<Grid x:Name="LayoutRoot" > 
    <ContentControl Style="{StaticResource BgBlueTop}"/> 
        <Border > 
            <ItemsControl ItemsSource="{Binding Messages}"> ... </ItemsControl> 
        </Border> 
</Grid>

Basically, the xaml parser can interpret an attribute as a string literal value or convert it to an object through some means.  Markup extensions allow you to do the deciding about how the value you’re setting should be interpreted by the xaml parser.  For a much more in depth look at how this all works, a decent place to start is this link on MSDN:

http://msdn.microsoft.com/en-us/library/ms747254.aspx

One interesting use of MarkupExtensions I’ve been playing with is a reimplementation of the Binding markup extension to provide an alternative to the IValueConverter interface. Sometimes you really only need to do a conversion once or a couple times on a specific screen.  When you implement a value converter it feels like you are taking a tiny bit of view or business logic and stuffing it in an unrelated portion of your application.  That being said, a standardized library of value converters like boolean-to-visibility and so on can make developing on a project much easier to use.  But for the one off scenarios, it’d be nice to keep all that logic contained in your ViewModel and not have to worry about spinning up a new class for such a simple thing.

I used the post here as a starting point for my custom binding because working with Binding or BindingBase was not going so well.  From there I created my own Binding class and added a ConverterDelegate property.  This property looks for a method on the same DataContext of the binding and uses a generic IValueConverter behind the scenes to call that method of the DataContext.  This helps get rid of all those little one-off classes that you have to create for specific conversion scenarios.

The code is far from production ready but the gist of it is that a custom MarkupExtension overrides the ProvideValue method of the abstract MarkupExtension class. In the background I look up the method on my DataContext and use a IValueConverter that calls that method to do the conversion. So to wire up my converter I can simply do this:

<Window x:Class="CustomMarkup.Window1" 
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
	xmlns:local="clr-namespace:CustomMarkup" Title="Window1" Height="300" Width="300"> 
	<Grid> 
           <Button Content="{local:ExBinding Path=ButtonText, ConverterDelegate=ToUpper}" Height="25" Width="100"/> 
	</Grid> 
</Window>

You can see I have a converter delegate called ToUpper and in my code behind or ViewModel I can simply write whatever methods I need to do conversions like this:

public partial class Window1 : Window
{
	public Window1()
	{
		DataContext = this;
		InitializeComponent();
	}

	// our converter method
	public object ToUpper(object value)
	{
		return (object)value.ToString().ToUpper();
	}

	public string ButtonText { get; set;}
}

I can post the sample project if I get interest but the real point is to give a small showing of what’s possible with custom MarkupExtensions in WPF and SL5.

Uses for Silverlight reflection, pt. II

So, as promised, here is the followup to what I was doing with Silverlight reflection that made me need access to Internal members of a class.

Localization in Silverlight is still an interesting story and everybody seems to have their own way of doing it.  The client I’m on uses Excel spreadsheets that load into a database. The localization data then pulls when a usercontrol loads and changes the controls data based on the locale and what was in the database.

This was very tedious for developers to setup.  You would create your UI and then have to go back and pull the default text for your controls and add them all to the spreadsheet.

Using reflection I can create an instance of all the user controls in my assembly and display them to the user in a listbox.  From there, when they select a user control, I can reflect on that type and display all the controls defined in the UserControl to the user.  When you define a control in xaml and give it a name, it becomes an internal member of a partial class generated by Visual Studio.

So, what I do is when you are all done with your UserControl you simply run my tool on the assembly and it reflects through and shows all the UserControls. When you select one, it uses reflection to create an instance with the default constructor, which initializes all your controls properties.

From there I grab all the controls through reflection and use some logic to get which properties of each I want to localize.  For TextBlocks I grab the Text property, for ContentControls it’s the Content property, and so on.

Using that I generate a simple tab-delimited string with all the default localization for all the controls and the user can copy/paste right into Excel and move on to their next task and let someone else do the translating/localizing for them.

Silverlight Reflection and internal members

If you want to use reflection in Silverlight you have to come to grips with the fact that you can only reflect on public members of the class.  This is a very important part of the security features in Silverlight.

However, I have a scenario that would be greatly helped by being able to reflect on internal members.  The documentation I found on MSDN said that as long as the member was visible at compile time you could reflect on it.  This should include internal members in the same assembly or an assembly that’s the target of InternalsVisibleTo.

I was having problems, at first I just tried setting the InternalsVisibleTo attribute in the AssemblyInfo.cs for my project to the project that had my reflection code. 

No such luck, even though I could access the members through normal means.  What I was missing was setting the BindingFlags attribute while calling GetMembers on my type. 

If you pass in BindingFlag.NonPublic | BindingFlags.Public | BindingFlags.Instance it should all work for you now.

Up next will be a post sometime about why I wanted this ability.