Reputation:
I have a code that allows you to create objects on the screen, there is a panel of buttons, clicking on the button you create an image / object on canvas, I can not get another image to be placed in Canvas so that several images can be displayed, link to a previously created question: WPF C # Display objects (2d Map)
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Canvas>
<Image x:Name="injWell" Source="/Resources/injectionWell.png"
HorizontalAlignment="Center" VerticalAlignment="Center"
Width="40" Height="40"
Stretch="Fill" StretchDirection="Both" IsHitTestVisible="False"/>
<Image x:Name="injWellNot" Source="/Resources/injectionWellNot.png"
HorizontalAlignment="Center" VerticalAlignment="Center"
Width="40" Height="40"
Stretch="Fill" StretchDirection="Both" IsHitTestVisible="False"/>
<TextBlock Canvas.Top="-20" Canvas.Left="-40" Width="100"
TextAlignment="Center" Text="{Binding Name}" FontWeight="Bold"
IsHitTestVisible="False"
Visibility="{Binding DataContext.ShowNames,
RelativeSource={RelativeSource FindAncestor, AncestorType=Window},
Converter={StaticResource BoolToVisibilityConverter}}"/>
<TextBlock Canvas.Left="30" Canvas.Top="10"
Text="{Binding X, StringFormat='{}X = {0}'}"
IsHitTestVisible="False"
Visibility="Collapsed" x:Name="XText"/>
<TextBlock Canvas.Left="30" Canvas.Top="25"
Text="{Binding Y, StringFormat='{}Y = {0}'}"
IsHitTestVisible="False"
Visibility="Collapsed" x:Name="YText"/>
</Canvas>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="injWell" Property="Source" Value="/Resources/injectionWell.png"/>
<Setter TargetName="injWellNot" Property="Source" Value="/Resources/injectionWellNot.png"/>
</Trigger>
<DataTrigger Binding="{Binding DataContext.ShowAllCoordinates, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="True">
<Setter TargetName="XText" Property="Visibility" Value="Visible"/>
<Setter TargetName="YText" Property="Visibility" Value="Visible"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True"/>
<Condition Binding="{Binding DataContext.ShowCurrentCoordinates, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="XText" Property="Visibility" Value="Visible"/>
<Setter TargetName="YText" Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</DataTemplate>
Upvotes: 0
Views: 925
Reputation: 16119
The key thing to realize here is that you need to render a list of items, and in MVVM you do that with an ItemsControl. (You could also use a ListView, but they implement additional functionality that you almost certainly wont want, like item selection etc). Ultimately you want all of your graphics objects to be displayed on a Canvas, so you need to override the ItemsPanel property and put one there inside a ItemsPanelTemplate. Each element then needs to be positioned on the Canvas, so you'll need to set the ItemContainerStyle and set the Canvas.Left and Canvas.Top properties there (a common mistake is to do it on the elements themselves, but they get placed into a container so you have to do it on that instead). Put all this together and you'll have something that looks like this:
<ItemsControl ItemsSource="{Binding MyGraphicsViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
So MyGraphicsViewModels will typical be a list in your view model of some base class you've created (e.g. BaseGraphicsViewModel) and then you'll subclass that into all the different types of graphics items you want to draw. The final piece of the puzzle is to then add DataTemplates to specify how you want each of your view model types to be represented in the view:
<DataTemplate DataType="{x:Type vm:DerivedGraphicsObjectViewModel}">
<Rectangle Fill="Blue" Width="64" Height="64" />
</DataTemplate>
For a more comprehensive example, which uses Triggers instead of DataTemplates, check out my answer to this SO question from the past.
Upvotes: 2