我有一个自定义Panel,我在其中声明了一个自定义属性来保存内容(我不想使用Children作为内容):
[ContentProperty(Name = "PanelContent")]
public class CustomPanel : Panel
{
public static readonly DependencyProperty PanelContentProperty =
DependencyProperty.Register("PanelContent",
typeof(Collection<UIElement>), typeof(CustomPanel),
new PropertyMetadata(new Collection<UIElement>(), null));
public Collection<UIElement> PanelContent
{
get
{
return (Collection<UIElement>)GetValue(PanelContentProperty);
}
}
}
这样使用时效果非常好:
<CustomPanel>
<TextBlock>A</TextBlock>
<TextBlock>B</TextBlock>
</CustomPanel>
但是当我想在ItemsControl中使用面板作为ItemsPanelTemplate时,ContentProperty属性将被忽略并将所有内容添加到 Children 集合,而不是 PanelContent 集合:< / p>
<ItemsControl ItemTemplate="{StaticResource ReviewTemplate}" ItemsSource="{Binding Reviews}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<CustomPanel></CustomPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
这不是它应该如何运作的。根据{{3}}:
ItemsPanelTemplate对象元素应该只包含一个FrameworkElement派生类,该类用作项的根元素。在大多数情况下,这是一个Panel派生类。扩展模板用作已实现项目的父项,并且通常存在多个项目。因此,ItemsPanelTemplate的预期根元素的XAML内容属性应该支持集合,如Panel.Children那样。
答案 0 :(得分:2)
Panel的GenerateChildren方法,负责此任务的外观(如ILSpy所示),如
internal virtual void GenerateChildren()
{
IItemContainerGenerator itemContainerGenerator = this._itemContainerGenerator;
if (itemContainerGenerator != null)
{
using (itemContainerGenerator.StartAt(new GeneratorPosition(-1, 0), GeneratorDirection.Forward))
{
UIElement uIElement;
while ((uIElement = (itemContainerGenerator.GenerateNext() as UIElement)) != null)
{
this._uiElementCollection.AddInternal(uIElement);
itemContainerGenerator.PrepareItemContainer(uIElement);
}
}
}
}
如您所见,它总是添加到this._uiElementCollection,这是支持Children属性的字段。
答案 1 :(得分:1)
我认为ItemsPanelTemplate只能将Panel.Children作为布局项目的目标。事实上,如果您从ContentControl派生CustomPanel,您将在metro风格应用程序中找到以下异常消息:
Exception: The ItemsControl.ItemsPanelTemplate must have a derivative of Panel as the root element.
您链接的文档可能是从WPF时间复制的文档错误,此时您仍然可以通过编程方式将可视化插入到可视树中。在Metro应用程序中,不再使用Panel.Children将您自己的UIElements列表放入可视树中。
答案 2 :(得分:0)
因为ItemsControl使用ItemsPanelTemplate来创建和使用Panel,而不是XAML做任何事情。无论ContentProperty设置为什么,ItemsControl都会调用Panel.Children.Add。
Panel应该只布置子项,而不是它们的样式。所以你必须做的只是覆盖排列和测量方法。所有面板都是这样做的。
对于样式和任何其他逻辑,您必须使用其他方法。