Rob Relyea

xaml:Blog

XAML Markup Extensions

Markup Extensions are documented in the Windows SDK here.

In addition to what that document says, you can also use Markup Extensions as elements.  Not just in attributes.

Somebody asked a question if you could have a tag map to an interface...the answer is no.  But you can have a tag map to a markup extension and do what ever you want in there.  This is a quick example of that.

I've built a sample MarkupExtension called ClassFactory and added it my small set of downloadable samples.

Here is a picture of this demo:

 

XAML\MEasOE.xaml

...
    <Button>
      <RadioButton>test button</RadioButton>
    </Button>
    <Button>
      <Button.Content>
        <!-- Button.Content should not be necessary, but a bug requires it in this build-->
        <my:ClassFactory Type="RadioButton">
          <my:ClassFactory.Properties>
            <my:NameValuePair Name="Content" Value="Test button 2" />
          </my:ClassFactory.Properties>
        </my:ClassFactory>
      </Button.Content>
    </Button>
...

ClassFactory.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Serialization;
using System.Reflection;

namespace WpfDemos.XAML
{
    public class ClassFactory : MarkupExtension
    {
        public ClassFactory()
        {
        }
        private Type _Type;
        public Type Type
        {
            get { return _Type; }
            set { _Type = value; }
        }
        private List<NameValuePair> _Properties;
        public List<NameValuePair> Properties
        {
            get
            {
                if (_Properties == null)
                    _Properties = new List<NameValuePair>();
                return _Properties;
            }
        }

        //Provide value is called and the return value is used by
        //the XamlReader instead of the MarkupExtension.
        //This could be used to do additional work that normal XamlReading rules don't
        //support.
        public override object ProvideValue(object targetObject, object targetProperty)
        {
            object o =  Type.Assembly.CreateInstance(Type.FullName);
            foreach (NameValuePair prop in Properties)
            {
                PropertyInfo pi = Type.GetProperty(prop.Name);
                //This would need to add typeconverter support to set types that aren't
                //assignable by strings.
                pi.SetValue(o, prop.Value, null);
            }
            return o;
        }

    }
}

Posted on Feb 03 2006, 06:57 PM by rrelyea
Filed under: ,
PostTypeIcon
22,244 Views

Comments

  • jfo's coding said:
    I thought I'd put up a few good reads:

    Mapping PIs are going away in the next CTP. Rob promises to...
    February 14, 2006 11:14 PM