Default Constructor Parameter in MarkupExtension declaration

一笑奈何 提交于 2020-12-28 18:24:18

问题


Reducing this question to the bare minimum, consider this MarkupExtension class...

public class ProblemStatement : MarkupExtension
{
    private readonly string _first;
    private readonly string _second;
    public ProblemStatement(string first, string second)
    {
        _first = first;
        _second = second;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
    public override string ToString()
    {
        return _first + _second;
    }
}

When this Xaml is declared...

<Grid>
    <TextBlock Name="TextBlock1" Tag="{so:ProblemStatement 'hello', 'world'}"/>
    <TextBlock Text="{Binding ElementName=TextBlock1, Path=Tag}"/>
</Grid>

...you see 'helloworld' in the TextBlock as expected. All's well to this point.

But changing the constructor parameter to this...

public ProblemStatement(string first, string second = "nothing")

...and the relevant Xaml to this...

   <Grid>
        <TextBlock Name="TextBlock1" Tag="{so:ProblemStatement 'hello'}"/>
        <TextBlock Text="{Binding ElementName=TextBlock1, Path=Tag}"/>
    </Grid>

the resulting error message is...

No constructor for type 'ProblemStatement' has 1 parameters.

There is a work-around, which is to chain the constructor by adding this statement to the class...

public ProblemStatement(string first) : this(first, "not provided") { }

and this will show 'hellonot provided' in the TextBlock. However, this also changes the semantics of the MarkupExtension and is not desirable in the larger, 'real-world' case. Also the complexity of overloading increases dramatically when more complex types are used or the constructor arguments are of type 'dynamic'. Also, for example, use of the new 'Caller Information' attributes is blocked altogether.

So the question is: how to declare the Xaml so that the Xaml parser will honour a default constructor argument?


回答1:


Try this out:

    public string Optional{ get; set; } = "DefaultValue";

    private readonly string _mandatory;

    public ProblemStatement(string mandatory)
    {
        _mandatory = mandatory;
    }

Usage:

<TextBlock Name="TextBlock1" Tag="{local:ProblemStatement 'hello', Optional=NotDefault}"/>

Alternative:

<TextBlock Name="TextBlock1" Tag="{local:ProblemStatement 'hello'}"/>

Result:

  • No XAML parsing errors
  • No need to overload the constructor for optional parameters
  • Mandatory parameters are constructor parameters.
  • Optional parameters are properties.


来源:https://stackoverflow.com/questions/23711972/default-constructor-parameter-in-markupextension-declaration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!