尝试做这样的事情......
public class MiniObject
{
public bool Checked { get; set; }
public String Caption { get; set; }
public ICollection<MiniObject> Content { get; set;}
}
<Window.Resources>
<local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
<local:MiniObject.Content>
<local:MiniObject Caption="Item1" Checked="True">
</local:MiniObject>
<local:MiniObject Caption="Item2" Checked="True">
</local:MiniObject>
</local:MiniObject.Content>
</local:MiniObject>
</Window.Resources>
这当然无法返回错误:
Object of type 'WorkflowTest.MiniObject' cannot be converted to type 'System.Collections.Generic.ICollection`1[WorkflowTest.MiniObject]'.
有没有办法在WPF中执行此操作?如果是这样,我需要完全改变对象的形状,或者我只需提供一个只有WPF使用的专用对象......
<Window.Resources>
<local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
<local:MiniObject.Content>
<local:MiniObjectCollection>
<local:MiniObject Caption="Item1" Checked="True">
</local:MiniObject>
<local:MiniObject Caption="Item2" Checked="True">
</local:MiniObject>
</local:MiniObjectCollection>
</local:MiniObject.Content>
</local:MiniObject>
</Window.Resources>
答案 0 :(得分:1)
您正在尝试使用XAML的隐式集合语法。为此,属性(在本例中为Content
)必须是实现ICollection
的类型。注意:不是ICollection
,而是实现ICollection
的类型。
您不能只使用接口,因为XamlReader
需要知道要创建的对象类型。如果你没有告诉它类型,它应该如何决定?通过搜索程序集可用的所有类型,找到实现ICollection<MiniObject>
的那些类型,丢弃那些没有无参数构造函数的类型,然后随机选择一个?没有。
将Content
定义为List<MiniObject>
时,XamlReader
知道应该创建的对象类型。由于这是一种实现ICollection
的类型,因此它可以使用隐式集合语法。所以它只是创建对象并调用Add
来添加子项,如果你在那里放了一个不是MiniObject
的子项,你就会遇到运行时错误。
您在Content
媒体资源中说“我需要避免使用实际的实现”。在这种情况下,您不能使用隐式集合语法。您需要在第二个示例中执行操作:显式定义实现ICollection<MiniObject>
的类型,并在XAML中添加子元素以显式创建它。
答案 1 :(得分:1)
仅使用上面提到的代码,由于来自MSDN的事实,它将作为空引用异常抛出,以在XAML中编写集合属性:
The presence of that collection type is implicit whenever you specify a property
in XAML that takes a collection type.
因此,如果您不希望在类声明中拥有集合实例,我建议在XAML中初始化集合,如下所示。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System.Collections;assembly=mscorlib" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MiniObject x:Key="RootItem" Caption="Item0" Checked="True">
<local:MiniObject.Content>
<system:ArrayList> -------------------------------------1)
<local:MiniObject Caption="Item1" Checked="True">
</local:MiniObject>
<local:MiniObject Caption="Item2" Checked="True">
</local:MiniObject>
</system:ArrayList>
</local:MiniObject.Content>
</local:MiniObject>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=RootItem}, Path=Content}" DisplayMemberPath="Caption"/>
</Grid>
</Window>
public class MiniObject
{
public bool Checked { get; set; }
public String Caption { get; set; }
public IList Content { get; set; } -----------------------------------------2)
}
在2),你可能知道有四种选择(IList,IDictionary等)作为XAML中的集合属性。请参阅MSDN。上面,ICollection也可以,因为这些项被添加到ArrayList。
在1),我们还不能声明一个泛型类型集合,但我知道它会很快得到支持。
答案 2 :(得分:0)
我也有类似的要求,并且以与@NtscCobalt相同的方式实现并获得相同的异常,
此异常的一个简单解决方案是使用List&lt;&gt;的一些集合初始化Content属性。或OvservableCollection&lt;&gt;。
这对我有用。 此外,如果您使用IEnumerable而不是IList,它将给出构建错误。
private IList<MiniObject> _content = new List<MiniObject>();
public IList<MiniObject> Content
{
get
{
return _content;
}
set
{
_content=value;
}
}