WPF - ItemTemplate不按预期工作

4
我有一个`UserControl`,用于显示一个`UIElement`列表。该控件包括一个单独的`ItemsControl`,其`ItemPanelTemplate`切换为水平的`StackPanel`,其`ItemsSource`绑定到`UserControl`公开的一个`DependencyProperty`,并在`UserControl.Resources`中设置了其`ItemTemplate`。除了`ItemTemplate`从未应用之外,一切都正常。我不知道原因。完整源代码如下。
<UserControl x:Name="UC" x:FieldModifier="private" x:Class="ContentSliderControl.ContentSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>

    <DataTemplate x:Key="pageTemplate">
        <Border CornerRadius="10" Padding="5" Height="200" Width="200" Background="#333">
            <ContentControl Content="{Binding}"/>
        </Border>
    </DataTemplate>

    <ItemsPanelTemplate x:Key="template">
        <StackPanel IsItemsHost="True"
            Orientation="Horizontal"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled"
            ScrollViewer.VerticalScrollBarVisibility="Disabled"/>
    </ItemsPanelTemplate>
</UserControl.Resources>

<ItemsControl ItemsPanel="{StaticResource template}" 
              ItemTemplate="{StaticResource pageTemplate}" 
              ItemsSource="{Binding ElementName=UC,Path=Pages}"/>

UserControl.xaml.cs - 用户控件代码文件

[ContentProperty("Pages")]
public partial class ContentSlider : UserControl
{


    public List<UIElement> Pages
    {
        get { return (List<UIElement>)GetValue(PagesProperty); }
        //set { SetValue(PagesProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Pages.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PagesProperty =
        DependencyProperty.Register("Pages", typeof(List<UIElement>), typeof(ContentSlider), new UIPropertyMetadata(null));



    public ContentSlider()
    {
        InitializeComponent();
    }
}

我这样在主窗口中使用控件 -

    <slider:ContentSlider >
    <slider:ContentSlider.Pages>
        <Button>1</Button>
        <Button>2</Button>
        <Button>3</Button>
        <Button>4</Button>
    </slider:ContentSlider.Pages>
</slider:ContentSlider>

按钮显示正常,但不在200px的正方形边框内。
非常感谢您的帮助。 谢谢。
5个回答

6
Nir是正确的,如果它们是UI元素,ItemsControl会直接将项目添加到其Panel中。我在MSDN中没有找到任何关于此行为的提及,但Dr. WPF在他关于项容器的文章中提到了它:

如果将UIElement添加到显式ItemsControl实例(而不是ListBox等派生类的实例)的Items集合中,则它将成为items panel的直接子级。如果添加非UIElement,则将在ContentPresenter中包装它。

您的解决方案可能是改用ListBox,并将ItemContainerStyle设置为ListBoxItem的新Style,在该样式中使用包含BorderControlTemplate

这行为有点疯狂呢。感谢你的回答,Robert,我会给Nir正确的答案并为你投票的。可惜只能有一个正确的答案,是吧? - EightyOne Unite

4
尼尔是正确的,这个自定义的ItemsControl实现将解决问题并允许使用您自己的ItemTemplate:
public class ItemsControlForUIElement : ItemsControl
{
   protected override DependencyObject GetContainerForItemOverride()
   {
       return new ContentPresenter();
   }
   protected override bool IsItemItsOwnContainerOverride(object item)
   {
       return false;
   }
}

4

这是因为它是一个UIElement列表,只有在项目无法直接显示时才应用项目模板。


另外,如果我将ItemsControl替换为Listbox,则它们会按预期呈现,因此我不确定您的说法是否正确。 - EightyOne Unite
看来我得收回之前的话了!谢谢Nir。 - EightyOne Unite

2

Robert Macnee准确地指出了原因。他的解决方案涉及使用控件模板,这可能对于特定情况来说有些过度。或者,可以使用ListBox - 将ItemContainerStyle设置为ListBoxItem的新样式,并在该样式中将ContentTemplate设置为您想要在ListBox ItemTemplate中使用的DataTemplate


-1
如果您在 DataTemplate 上设置了 DataType 属性,它就会开始工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接