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}}"/>