问题
I have a UserControl
which I'm using to display a list of UIElement
s. The control consists of a single ItemsControl
with it's ItemPanelTemplate
switched for a horizontal StackPanel
, its ItemsSource
bound to a DependencyProperty
exposed by the UserControl
and its ItemTemplate
set in the UserControl.Resources
.
Everything works fine except the ItemTemplate
never get's applied and I can't see why. The full source is below.
UserControl.xaml -
<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();
}
}
}
I consume the control in my main window like this -
<slider:ContentSlider >
<slider:ContentSlider.Pages>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<Button>4</Button>
</slider:ContentSlider.Pages>
</slider:ContentSlider>
The buttons appear fine but not inside the 200px square border.
Any help would be greatlly appriciated. Thanks.
回答1:
It's because it's a list of UIElement, the item template is only applied if the items can't be displayed directly.
回答2:
Nir is correct, ItemsControl
will add item directly to its Panel
if they are UIElements. I couldn't find any mention of this behavior in MSDN, but Dr. WPF mentions it in his article on item containers:
If a UIElement is added to the Items collection of an explicit ItemsControl instance (as opposed to an instance of a derived class like ListBox), it will become a direct child of the items panel. If a non-UIElement is added, it will be wrapped within a ContentPresenter.
Your solution is probably to use a ListBox
instead, and set ItemContainerStyle
to a new Style
for ListBoxItem
, and in that style, use a ControlTemplate
with your Border
in it.
回答3:
Nir is right, this custom ItemsControl implementation will solve the issue and let use your own ItemTemplate:
public class ItemsControlForUIElement : ItemsControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentPresenter();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return false;
}
}
回答4:
Robert Macnee nailed the reason on the head. His solution involves using the control template which might be overkill for a given scenario. Alternatively, use a ListBox
- set the ItemContainerStyle
to a new Style for ListBoxItem
, and in that style, set the ContentTemplate
to the DataTemplate
that you wanted to use in the ListBox
ItemTemplate
.
回答5:
If you set the DataType
property on the DataTemplate
it would start working.
来源:https://stackoverflow.com/questions/661831/wpf-itemtemplate-not-acting-as-expected