この質問を最小限に減らして、この MarkupExtension クラスを検討してください...
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;
}
}
この Xaml が宣言されると...
<Grid>
<TextBlock Name="TextBlock1" Tag="{so:ProblemStatement 'hello', 'world'}"/>
<TextBlock Text="{Binding ElementName=TextBlock1, Path=Tag}"/>
</Grid>
...期待どおり、TextBlock に「 helloworld 」が表示されます。ここまでは順調です。
しかし、コンストラクターのパラメーターをこれに変更します...
public ProblemStatement(string first, string second = "nothing")
...そしてこれに関連するXaml...
<Grid>
<TextBlock Name="TextBlock1" Tag="{so:ProblemStatement 'hello'}"/>
<TextBlock Text="{Binding ElementName=TextBlock1, Path=Tag}"/>
</Grid>
結果のエラーメッセージは...
No constructor for type 'ProblemStatement' has 1 parameters.
このステートメントをクラスに追加してコンストラクターをチェーンするという回避策があります...
public ProblemStatement(string first) : this(first, "not provided") { }
これにより、TextBlock に「 hellonot provided 」が表示されます。ただし、これは MarkupExtension のセマンティクスも変更するため、より大きな「現実世界」のケースでは望ましくありません。また、より複雑な型が使用されているか、コンストラクターの引数が「動的」型である場合、オーバーロードの複雑さは劇的に増加します。また、たとえば、新しい「発信者情報」属性の使用は完全にブロックされます。
問題は、Xaml パーサーが既定のコンストラクター引数を受け入れるように Xaml を宣言する方法です。