我正在尝试从XAML填充依赖项属性。依赖项属性是IEnumerable<KeyAction>
,其中KeyAction是复杂类型。
<loc:MyType.KeyActions>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:MyType.KeyActions>
现在,这导致KeyAction
属性被'声明两次',因为XAML将每个项目解释为属性的候选项,而不是列表中的项目。
要使其工作,需要看起来像:
<loc:CompletionPopupView.KeyActions>
<sys:List`KeyAction>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</sys:List`KeyAction>
</loc:CompletionPopupView.KeyActions>
我需要添加命名空间,如果可行的话,通用语法可能更加糟糕。有没有办法让第一个例子有效?
答案 0 :(得分:22)
有两种不同的方法可以完成这项工作。一个看起来与你的第一个例子完全一样,但需要改变你的课程,并且不能按照你要求的方式运行(这对你来说可能是也可能不是问题);其他行为就像你问的那样,但是更加冗长。你可以决定哪一个更适合你。
XAML使用您在第一个示例中显示的确切语法,使用魔术速记语法初始化集合。但是,它仅在属性类型实现IList
时有效。 (是的,这确实是非泛型 IList
- 通常不是什么大问题,.NET附带的所有通用集合都实现了IList<T>
和{{1 }}。)
所以你可以做你的第一个例子,但前提是你的IList
属性被声明为实现KeyActions
的类型。例如,您可以将您的属性更改为:
IList
然后只需在您的属性中放入多个子元素,它就会将它们添加到集合中:
public ObservableCollection<KeyAction> KeyActions { get {...} }
这与您的要求不太相似,因为XAML不会创建新集合 - 它会添加到现有集合中。因此,如果选择此选项,则您的类需要在其构造函数(<loc:MyType.KeyActions>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:MyType.KeyActions>
)中实例化集合,以便在开始尝试KeyActions = new ObservableCollection<KeyAction>();
元素时不会获得空引用异常。
如果您确实需要创建一个新的集合并将其分配给您的财产,那也是可行的。不幸的是,XAML2006(WPF仍然使用的风格)仅支持整个文档的根元素上的泛型 - 因此您无法实例化Add
并将其分配给属性。
但那没关系;您可以使用WPF执行的相同解决方法。只需创建一个属于通用列表的非泛型类。
List<T>
然后你可以在XAML中实例化它:
public class KeyActionCollection : ObservableCollection<KeyAction> {}
如果您选择此选项,则可以根据需要将您的媒体资源声明为<loc:CompletionPopupView.KeyActions>
<loc:KeyActionCollection>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:KeyActionCollection>
</loc:CompletionPopupView.KeyActions>
。自定义列表仅用于从XAML填充列表。
您甚至可以结合使用两种方法:使属性读/写并且类型为IEnumerable<KeyAction>
,在构造函数中实例化它,然后XAML可以选择是使用简写语法添加到现有集合,还是创建新系列;和运行时代码可以做出相同的选择。