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.
To get the detail information about the type we need to get the IXamlTypeResolver service requested by ISserviceProvide interface. Its code is quite simple.
IXamlTypeResolver interface also contain only one method. Here is a class diagram of IXamltypeResolver interface.
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.
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.
{
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.
{
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
<ListBox Margin="5" ItemsSource="{local:MyTypeMarkup TypeName=local:MyClass}"/>
Here is complete C# code of the program.
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.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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.

