Reputation: 27
I am creating an application in WPF using the MVVM approach. I am fairly new to the topic and I'm looking on pointers how to achieve the following: I have created a canvas in XAML, as follows:
<canvas name = "myCanvas">
...
</canvas>
I added a button, also in XAML, which I want to use to draw (programmatically) some basic shapes (line, rectangle, etc.) onto the existing canvas on mouse click. Since I'm using the MVVM approach, the button's command has to be bound to a method, as follows:
<Button name="myButton" Command="{Binding myMethod, Mode=OneWay}">
...
</Button>
I got the binding itself to work fine and I created the drawings and shapes in C#, but I don't understand how can I put the shapes onto the canvas that was created in XAML. How can I address the canvas pre-made in XAML from my method? How do I go about this?
Edit:
The point of this is that I want to generate shapes based on data to visualise it. So, if my input has, say, 3 elements of type A, I want to create 3 rectangles and display them on the canvas. Later I want to make them clickable and display some information about them on click. MVVM is a set requirement for me.
Upvotes: 2
Views: 1624
Reputation: 128013
In your view model you should have a representation of the shapes that does not use any UI elements:
public class ShapeItem
{
public Geometry Geometry { get; set; }
public Brush Fill { get; set; }
public Brush Stroke { get; set; }
}
public class ViewModel
{
public ObservableCollection<ShapeItem> ShapeItems { get; set; }
}
You would then use an ItemsControl with an appropriate ItemsPanel
and ItemTemplate
to visualize the shape items:
<ItemsControl ItemsSource="{Binding ShapeItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
Stroke="{Binding Stroke}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The view model might be initialized like shown below, and items may be added similarly when an appropriate command method is executed:
var vm = new ViewModel();
vm.ShapeItems = new ObservableCollection<ShapeItem>();
vm.ShapeItems.Add(
new ShapeItem
{
Geometry = new EllipseGeometry(new Point(100, 100), 100, 50),
Fill = Brushes.LightBlue
});
vm.ShapeItems.Add(
new ShapeItem
{
Geometry = new RectangleGeometry(new Rect(150, 100, 200, 100)),
Fill = Brushes.Azure,
Stroke = Brushes.Black
});
DataContext = vm;
Upvotes: 5