Search code examples
c#wpfxamldatatemplateitemscontrol

ItemsControl ignores DataTemplates in Resources


I want to bind a collection of multiple types to an ItemsControl being displayed in a canvas. My code so far is the following:

<ItemsControl ItemsSource="{Binding Path=Objects}">
     <ItemsControl.Resources>
         <DataTemplate DataType="self:CalibrationRectangle">
             <Rectangle Fill="{Binding Path=Color, Converter={StaticResource ColorToBrushConverter}}" Width="{Binding Width}" Height="{Binding Height}" />
         </DataTemplate>
         <DataTemplate DataType="self:PolygonVM">
             <Polygon Fill="{Binding Path=Color, Converter={StaticResource ColorToBrushConverter}}" Points="{Binding Points}" />
         </DataTemplate>
     </ItemsControl.Resources>
     <ItemsControl.ItemsPanel>
         <ItemsPanelTemplate>
             <Canvas Background="Red" />
         </ItemsPanelTemplate>
     </ItemsControl.ItemsPanel>
     <!--<ItemsControl.ItemTemplate>
         <DataTemplate DataType="self:CalibrationRectangle">
             <Rectangle Fill="{Binding Path=Color, Converter={StaticResource ColorToBrushConverter}}" Width="{Binding Width}" Height="{Binding Height}" />
         </DataTemplate>
     </ItemsControl.ItemTemplate>-->
     <ItemsControl.ItemContainerStyle>
         <Style>
             <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
             <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
         </Style>
     </ItemsControl.ItemContainerStyle>
</ItemsControl>

In this state of the code the DataTemplates in the Resources are completely ignored and instead objects are represented as strings. If instead I use the commented out lines and define the DataTemplate in ItemsControl.ItemsTemplate it works. However, as I need multiple DataTemplates (one per type) this is no solution.

What is the problem here? Why are the DataTemplates in the resources not working?

Any ideas are appreciated :)


Solution

  • At the moment you target XML element name. If you want to target type you need to use {x:Type ...} and replace

    <DataTemplate DataType="self:CalibrationRectangle">
    

    with

    <DataTemplate DataType="{x:Type self:CalibrationRectangle}">
    

    From MSDN:

    To refer to the type name of the class, use the x:Type Markup Extension. If the template is intended for XML data, this property contains the XML element name.