在 XAML 中使用标记扩展填充集合属性失败
我正在尝试使用标记扩展提供的值填充集合(列表)属性。 如果提供集合的属性具有公共设置器,则执行此操作会出现问题。 我认为这是 XAML 实现(使用 .NET 3.5)中的一个错误,但我不确定。
考虑以下测试类
[ContentProperty("SettableList")]
public class Test : FrameworkElement
{
List<string> _settableList = new List<string>();
List<string> _justGettableList = new List<string>();
public List<string> SettableList { get { return _settableList; } set { _settableList = value; } }
public List<string> JustGettableList { get { return _settableList; } }
}
和以下标记扩展,它仅提供一个字符串。
public class ProvideStringExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return "Blah";
}
}
现在以下测试用例都可以正常工作: 赫兹
<!-- b) fill SettableList with explicit string: ok -->
<local:Test>
<local:Test.SettableList>
<sys:String>Hurz</sys:String>
</local:Test.SettableList>
</local:Test>
<!-- c) fill JustGettableList with string from markup extension: ok -->
<local:Test>
<local:Test.JustGettableList>
<local:ProvideStringExtension/>
</local:Test.JustGettableList>
</local:Test>
<!-- d) fill SettableList with string form markup extension by using "ContentProperty": ok -->
<local:Test>
<local:ProvideStringExtension/>
</local:Test>
但这个测试用例失败了:
<!-- e) fill SettableList with string from markup extension: FAILS -->
<!-- Throws (tries to convert the provided string to List<string>) -->
<local:Test>
<local:Test.SettableList>
<local:ProvideStringExtension/>
</local:Test.SettableList>
</local:Test>
失败的用例抛出一个异常,指出“string”无法转换为“List”。 有没有解释为什么在类似的情况 d) 和 c) 工作正常的情况下会失败?
I am trying to fill a collection (list) property with values provided by a markup extension.
There is a problem doing this if the property providing the collection has a public setter.
I think it is a bug in the XAML implementation (using .NET 3.5), but I am not sure.
Consider the following test class
[ContentProperty("SettableList")]
public class Test : FrameworkElement
{
List<string> _settableList = new List<string>();
List<string> _justGettableList = new List<string>();
public List<string> SettableList { get { return _settableList; } set { _settableList = value; } }
public List<string> JustGettableList { get { return _settableList; } }
}
and the following markup extension, which just provides a string.
public class ProvideStringExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return "Blah";
}
}
Now the following test cases all work fine:
Hurz
<!-- b) fill SettableList with explicit string: ok -->
<local:Test>
<local:Test.SettableList>
<sys:String>Hurz</sys:String>
</local:Test.SettableList>
</local:Test>
<!-- c) fill JustGettableList with string from markup extension: ok -->
<local:Test>
<local:Test.JustGettableList>
<local:ProvideStringExtension/>
</local:Test.JustGettableList>
</local:Test>
<!-- d) fill SettableList with string form markup extension by using "ContentProperty": ok -->
<local:Test>
<local:ProvideStringExtension/>
</local:Test>
But this test case fails:
<!-- e) fill SettableList with string from markup extension: FAILS -->
<!-- Throws (tries to convert the provided string to List<string>) -->
<local:Test>
<local:Test.SettableList>
<local:ProvideStringExtension/>
</local:Test.SettableList>
</local:Test>
The failing case throws an exception saying that 'string' cannot be converted to 'List'.
Is there an explanation why this fails where as the similar cases d) and c) work fine?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
XAML 解析器尝试做的第一件事是获取您获得的值并将属性“设置”为该值。所以它想要这样做:
如果没有setter并且属性实现了ICollection(也许是IList,我忘记了),那么它将尝试将项目添加到集合中:
他们可能已经颠倒了这个逻辑,但我确信为此做出了设计选择。
另外,我相信即使设置器是私有的,它仍然会失败。但这可能已经得到解决。
The first thing the XAML parser will try to do is take the value you get and "set" the property to that value. So it wants to do this:
If there is no setter and the property implements ICollection (maybe IList, I forget), then it will try to add the item to the collection:
They could have probably reversed this logic, but I'm sure there was a design choice made to do it this way.
Also, I believe even if the setter is private, then it will still fail. But that may have been fixed.