laserman
laserman

Reputation: 233

Display CompositeCollection of shapes in WPF

I would like to display different shapes in one Canvas (I have a solution on multiple Canvases - but that does not let me select all shapes, so it is worthless). I put my shapes in a CompositeCollection and use multiple DataTemplates in one ItemsControl. However, the programm does not display the Shapes, instead it displays the Property Names in the location X,Y.

This is the collection:

        Page.Collection.Add(new CollectionContainer() { Collection = Page.Lines });
        Page.Collection.Add(new CollectionContainer() { Collection = Page.Rectangles });
        Page.Collection.Add(new CollectionContainer() { Collection = Page.Circles });

This is part of the class page:

public class Page:ViewModelBase,INotifyPropertyChanged
{
    ObservableCollection<Line> lines = new ObservableCollection<Line>();
    ObservableCollection<Rectangle> rectangles = new ObservableCollection<Rectangle>();
    ObservableCollection<Circle> circles = new ObservableCollection<Circle>();
    CompositeCollection collection = new CompositeCollection();
    public CompositeCollection Collection
    {
        get
        {
            return collection;
        }

        set
        {
            collection = value;
            OnPropertyChanged("Collection");
        }
    }
    public ObservableCollection<Line> Lines
    {
        get
        {
            return lines;
        }

        set
        {
            lines = value;
            OnPropertyChanged("Lines");
        }
    }

Here is the XAML:

    <ItemsControl ItemsSource="{Binding Page.Collection}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas  IsItemsHost="True" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                    Background="Transparent">
                </Canvas>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Left" Value="{Binding Start.X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Start.Y}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.Resources>
            <DataTemplate DataType="Page.Lines">
                <Line X1="{Binding Start.X}" 
                    Y1="{Binding Start.Y}"
                    X2="{Binding End.X}"
                    Y2="{Binding End.Y}" Stroke="Black" StrokeThickness="1" />
            </DataTemplate>
            <DataTemplate DataType="Page.Rectangles">
                <Rectangle 
                    Width="{Binding Extend.X}"
                    Height="{Binding Extend.Y}" Stroke="Black" StrokeThickness="1" />
            </DataTemplate>
            <DataTemplate DataType="Page.Circles">
                <Ellipse
                    Width="{Binding Extend.X}"
                    Height="{Binding Extend.Y}" Stroke="Black" StrokeThickness="1" />
            </DataTemplate>
        </ItemsControl.Resources>
    </ItemsControl>

Upvotes: 0

Views: 1055

Answers (1)

dkozl
dkozl

Reputation: 33374

If you want to target specific class by DataType then you must specify type {x:Type ...}. Without that you target XML element as stated in DataTemplate.DataType:

If the template is intended for object data, this property contains the type name of the data object (as a string). 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. See the documentation remarks for details about specifying a non-default namespace for the XML element.

So your XAML should look like this

<DataTemplate DataType="{x:Type somenamespace:Line}">
    <!-- removed content -->
</DataTemplate>
<DataTemplate DataType="{x:Type somenamespace:Rectangle}">
    <!-- removed content -->
</DataTemplate>
<DataTemplate DataType="{x:Type somenamespace:Circle}">
    <!-- removed content -->
</DataTemplate>

where somenamespace is the namespace where Line, Rectangle and Circle classes are defined

xmlns:somenamespace="clr-namespace:Namespace.To.Your.Classes"

Upvotes: 1

Related Questions