Search code examples
c#wpfxamlmarkup-extensions

Markup extension naming


I'm pretty sure the answer is no, but is there a way to name a markup extension differently from the class that implements it?

I would like to make a markup extension that has a relatively short name:

<TextBlock Text="{my:Ext}"/>

but I would like to give it a different (longer) name on C# side:

public class MySpecificMarkupExtension : MarkupExtension

The only information I found about naming is on this page and the *Extension pattern, which is not what I want to achieve. I was hoping an Attribute would exists that allow me to do this:

[SomeAttribute("Ext")]
public class MySpecificMarkupExtension : MarkupExtension

But I've checked most of the attributes in the System.Windows.Markup namespace and there is no such attribute unfortunately.

Is there any solution to this problem?


Solution

  • The answer is as you may have already assumed NOPE. There is no such class attribute. None that I know.

    Since you mentioned you have a large amount of exceptions and you would like to keep xaml as simple as possible how about you have just one extension that calls others based on a key.

    Its like hiding all those extension behind a certain key.

    Take a look at this:

    public class MyExtExtension : MarkupExtension
    {
        public string Output
        {
            get; set;
        }
    
        public MyExtExtension(string output)
        {
            this.Output = output;
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this.Output;
        }
    }
    
    public class MarkupExtensionChooser : MarkupExtension
    {
        public string Key
        {
            get;
            set;
        }
    
        public StringList Param
        {
            get; set;
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (this.Key.Equals("ext"))
            {
                return new MyExtExtension(this.Param.Data[0]).ProvideValue(serviceProvider);
            }
    
            if (this.Key.Equals("ext123"))
            {
                // Custom Logic
            }
    
            if (this.Key.Equals("ext123123123"))
            {
                // Custom Logic
            }
    
            if (this.Key.Equals("ext123123123"))
            {
                // Custom Logic
            }
    
            if (this.Key.Equals("ext12121412423"))
            {
                // Custom Logic
            }
    
            return this;
        }
    }
    
    public class StringListTypeConverter : TypeConverter
    {
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                string val = (string)value;
                return new StringList(val.Split(','));
            }
    
            return null;
        }
    }
    
    [TypeConverter(typeof(StringListTypeConverter))]
    public class StringList
    {
        public string[] Data
        {
            get; set;
        }
    
        public StringList(string[] data)
        {
            this.Data = data;
        }
    }
    

    I ended up creating that "chooser class" which can also accept parameters and based on the key I return the necessary extension.

    The TypeConverter is just there to allow having Param="args1,args2,args3" in xaml.

    This is how my example in main window looks like:

    <TextBox Text="{local:MarkupExtensionChooser Key=ext, Param='hello,world'}"/>
    

    Hello will be displayed in TextBox since I pass param[0] to MyExtExtension.

    It works fine for me but I am not sure if you can use something like this.

    The idea is pretty simple however in the end its a bit of wpf tricking behind this and if you cannot follow let me know. I ll gladly assist you any futher.