Posted by: Zeeshan Amjad | June 15, 2011

Type Markup Extension


To write a markup extension, at minimum we need to do two things. First inherit our class from MarkupExtension class, and second override ProvideValue method of the MarkupExtension class. ProvideValue method takes only one parameter that is interface of IServiceProvider. This interface has only one method to get the available services. Here is a class diagram of this interface.

IServiceProvider

To get the detail information about the type we need to get the IXamlTypeResolver service requested by ISserviceProvide interface. Its code is quite simple.

Code Snippet
service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;

 

IXamlTypeResolver interface also contain only one method. Here is a class diagram of IXamltypeResolver interface.

IXamlTypeResolver

 

We created one property in our markup extension and passed the requested type in that property. We perform one additional check that if the given value is Enum type then display its value, otherwise display all the members of given type. For Enum type, we added one check to display the value only if IsLiteral property is set to true. Here is a piece of code to do this.

Code Snippet
Type type = service.Resolve(TypeName);

if (type.BaseType == typeof(Enum))
{
    return from field in type.GetFields()
            where field.IsLiteral == true
            select field.GetValue(null);
}
else
{
    return from member in type.GetMembers()
            select member.Name;
}

 

Here is complete code of MyTypeMarkupExtension.

Code Snippet
public class MyTypeMarkupExtension : MarkupExtension
{
    public string TypeName
    { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;

        if (service != null)
        {
            Type type = service.Resolve(TypeName);

            if (type.BaseType == typeof(Enum))
            {
                return from field in type.GetFields()
                        where field.IsLiteral == true
                        select field.GetValue(null);
            }
            else
            {
                return from member in type.GetMembers()
                        select member.Name;
            }
        }
        else
            return "";
    }
}

 

Now we created one Enum type and one class type to use this markup extension. Here is a code of it.

Code Snippet
public enum Directions
{
    East = 100, West, North, South
}

public class MyClass
{
    public int x { get; set; }
    public int y { get; set; }
    public int z { get; set; }
}

 

Here is XAML code to use this

Code Snippet
<ListBox Margin="5" ItemsSource="{local:MyTypeMarkup TypeName=local:Directions}"/>
<ListBox Margin="5" ItemsSource="{local:MyTypeMarkup TypeName=local:MyClass}"/>

 

Here is complete C# code of the program.

Code Snippet
using System;
using System.Linq;
using System.Windows;
using System.Windows.Markup;

namespace MarkupExtensionSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();            
        }
    }

    public enum Directions
    {
        East = 100, West, North, South
    }

    public class MyClass
    {
        public int x { get; set; }
        public int y { get; set; }
        public int z { get; set; }
    }

    public class MyTypeMarkupExtension : MarkupExtension
    {
        public string TypeName
        { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;

            if (service != null)
            {
                Type type = service.Resolve(TypeName);

                if (type.BaseType == typeof(Enum))
                {
                    return from field in type.GetFields()
                            where field.IsLiteral == true
                            select field.GetValue(null);
                }
                else
                {
                    return from member in type.GetMembers()
                            select member.Name;
                }
            }
            else
                return "";
        }
    }
}

 

And here is complete XAML code of the program.

Code Snippet
<Window x:Class="MarkupExtensionSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:MarkupExtensionSample"
        Title="MainWindow" Height="400" Width="600">
    <StackPanel>
        <ListBox Margin="5" ItemsSource="{local:MyTypeMarkup TypeName=local:Directions}"/>
        <ListBox Margin="5" ItemsSource="{local:MyTypeMarkup TypeName=local:MyClass}"/>
    </StackPanel>
</Window>

 

This is a output of the program.

MyMarkupExtensionOutput

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: