WPF - ItemTemplate does not work as expected

I have a UserControl that I use to display a list of UIElement s. The control consists of one ItemsControl , in which the ItemPanelTemplate switches to the horizontal StackPanel , its ItemsSource bound to the DependencyProperty , which is displayed by the UserControl and its ItemTemplate set in UserControl.Resources .

Everything works fine, except that ItemTemplate never applied, and I don't understand why. Full source 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 use the control in my main window as follows:

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

The buttons look great, but not inside the square border of 200 pixels.

Any help would be appreciated. Thanks.

+4
source share
5 answers

This is because it is a UIElement list, the element template is applied only if the elements cannot be displayed directly.

+4
source

Nir is true, ItemsControl will add an item directly to its Panel if they are UIElements. I could not find mention of this behavior on MSDN, but Dr. WPF mentions it in his article on containers for items :

If a UIElement is added to the Items collection of an explicit instance of ItemsControl (as opposed to an instance of a derived class such as a ListBox), it will become a direct child of the toolbox. If a non-UIElement is added, it will be wrapped in ContentPresenter.

Instead, you can use the ListBox and set the ItemContainerStyle to the new Style for the ListBoxItem , and in this style, use the ControlTemplate with your Border in it.

+6
source

Nir is right, this custom implementation of ItemsControl will solve the problem and allow you to use your own ItemTemplate:

 public class ItemsControlForUIElement : ItemsControl { protected override DependencyObject GetContainerForItemOverride() { return new ContentPresenter(); } protected override bool IsItemItsOwnContainerOverride(object item) { return false; } } 
+4
source

Robert McNee nailed his head on the head. Its solution involves the use of a management template that can be overwhelmed for a given scenario. Alternatively, use a ListBox - set the ItemContainerStyle to a new style for the ListBoxItem , and in this style set the ContentTemplate to the DataTemplate that you want to use in the ListBox ItemTemplate .

+2
source

If you set the DataType property to a DataTemplate , it will start working.

-1
source

All Articles