Reputation: 233
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
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