'Editable graphics in WPF

I am developing a WPF application that displays complex graphics to a window. I need these graphics to be highly dynamic, meaning that for instance lines can appear, disappear or just be moved at any time (by mouse interaction or programmatically).

Is there a way to achieve that without rebuilding the complete display list every time ? A typical case is that of the plot of a function where the data points can move, but not the rest. The points may be computed on the fly and not remembered in an array, so referring to their graphical representation is tricky.


Code example (on request):

// Add a Line Element
myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);

Update:

Assume I plot three functions. I draw the axis, the legends, the tick marks... and three curves.

Now is there a better way than redrawing everything if I want to remove the second curve ?



Solution 1:[1]

Is there a way to achieve that without rebuilding the complete display list every time ?

That's exactly what the MVVM pattern in general, and WPF templates together aim to provide. Specifically, you don't describe much of what you're trying to achieve except for this:

lines can appear, disappear or just be moved at any time

To me that sounds like two model classes, one for points (X and Y coordinates) and one for lines (that hold references to two points). The point model is observable (ie it implements INotifyPropertyChanged correctly and fully), while the line model should never change.

Coming to your view model, what you have is a collection of entities (something like IEntity), from which both models are derived. So simply a read only property of type ObservableCollection<IEntity>. When you want to move a point from a line, simply update its X and/or Y coordinate. Want to add a line? Add the points and the line connecting them to your collection. Same for deletion. Easy!

And the last part, your view. This holds an ItemsControl bound to your view model collection, with the panel template set to <Canvas/> (to be able to set location directly) and <DataTemplate> resources, one for each type of model you have:

  • Lines are simple, they're simply drawn in place by binding their four location properties to the X and Y coordinates of your two point models in your line model.
  • Points are where you get fancy, their purpose is to provide manipulators to move them around, ie a user control that responds to drag events for example and that updates its bound properties. Because lines hold references to your points, simply updating the point directly will reposition both the affected point visually, as well as the line that connects it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Blindy