7

I'm building a custom WPF control that derives from TabControl. In the ControlTemplate, I'm using a ItemsControl to display a list that is being bound from the template (an observable collection of type FileMenuItem). During program execution, I'm getting the following error in the output window:

ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='FileMenuItem'

The type FileMenuItem is derived from MenuItem. If I change the base class to DependencyObject, the code actually runs and the template is applied (so that's an option). I googled the error and couldn't find anything about it, has anyone run into this while developing custom controls? Even though I have a workaround, I'd like to understand what's happening, and I think using the MenuItem as a base class is a cleaner implementation.

I can post more code if it would help. Thanks!

Patrick White
  • 73
  • 1
  • 4

1 Answers1

7

The purpose of a DataTemplate (like ItemTemplate) is to provide a visualization for a data object. Specifically, it defines a set of elements to add to the visual tree in place of the data given to an ContentPresenter or ItemsPresenter. In your case your source list is a collection of objects that are already able to be added directly to the visual tree for display in the UI.

You can see this in the following simplified example where only "Three" shows up in Red because the first two items are defined in a form that can be displayed directly by ComboBox.

<ComboBox>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Foreground="Red"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
    <ComboBoxItem>One</ComboBoxItem>
    <ComboBoxItem>Two</ComboBoxItem>
    <sys:String>Three</sys:String>
</ComboBox>
John Bowen
  • 24,213
  • 4
  • 58
  • 56
  • 1
    Ok, I think I understand - so, is it possible to support this scenario, or do I need to switch to inheriting from a different base class? Thanks for your help! – Patrick White May 03 '10 at 20:19
  • 5
    There are a lot of different ways you could go. You should try to decide if you want to treat the collection items as controls (derived from UIElement) or data (INotifyPropertyChanged or DependencyObject) or create both a data class and a UI control or DataTemplate. Another possible option is a derived ItemsControl that overrides GetContainerForItemOverride and IsItemItsOwnContainerOverride to use a FileMenuItem container for each item (ComboBox, ListBox, etc do this). – John Bowen May 04 '10 at 02:50
  • 6
    One of the most simple (and effective) approaches to solving this problem for me has always been to derive your own ItemsControl, and override the `IsItemItsOwnContainerOverride` method to return false, which means the DataTemplate will not be skipped due to the problem John explained. – GEEF Oct 08 '14 at 15:37