Home > Software design >  How can you define the items of an array in a markup extension?
How can you define the items of an array in a markup extension?

Time:06-05

I wrote a custom WPF markup extension that formats a string. It looks like this:

using System;
using System.Windows.Markup;

namespace MarkupExtensions;

public class InterpolationExtension : MarkupExtension
{
    public object Value { get; set; }
    public object[] Arguments { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (Arguments is not null)
            return string.Format((string)Value, Arguments);

        return null;
    }

    public InterpolationExtension(object value)
    {
        Value = value;
    }

    public InterpolationExtension()
    {

    }
}

But if I want to use this in XAML, I have to use this clunky syntax (GreetMultiple is just a string resource "Hello, {0}, {1} and {2}!":

            <Run>
                <Run.Text>
                    <e:Interpolation>
                        <e:Interpolation.Value>
                            <StaticResource ResourceKey="GreetMultiple"/>
                        </e:Interpolation.Value>
                        
                        <e:Interpolation.Arguments>
                            <x:Array Type="{x:Type sys:String}">
                                <sys:String>A</sys:String>
                                <sys:String>B</sys:String>
                                <sys:String>C</sys:String>
                            </x:Array>
                        </e:Interpolation.Arguments>
                    </e:Interpolation>
                </Run.Text>
            </Run>

Is there some way to specify the array elements in one line like this?

<Run Text="{e:Interpolation Value={StaticResource GreetMultiple}, Arguments={x:Array Type={x:Type sys:String}, Items=[A,B,C]}}"/>

Everything about this works except for the [ ] syntax.

CodePudding user response:

You can use MarkupExtension to symplify the construction of array as well.

The MarkupExtension below can handle up to 5 elements buf if you need more elements, add more constructors.

[MarkupExtensionReturnType(typeof(object[]))]
public class ArrayConstructorExtension : MarkupExtension
{
    private readonly object[] _elements;

    public ArrayConstructorExtension(object a) => _elements = new[] { a };
    public ArrayConstructorExtension(object a, object b) => _elements = new[] { a, b };
    public ArrayConstructorExtension(object a, object b, object c) => _elements = new[] { a, b, c };
    public ArrayConstructorExtension(object a, object b, object c, object d) => _elements = new[] { a, b, c, d };
    public ArrayConstructorExtension(object a, object b, object c, object d, object e) => _elements = new[] { a, b, c, d, e };

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return _elements;
    }
}

Then it can be used as follows:

<Run Text="{e:Interpolation Value={StaticResource GreetMultiple}, Arguments={e:ArrayConstructor A, B, C}}"/>
  • Related