2
votes

Using the MVVM pattern I want to write lines and text to a Canvas much like a vector CAD application would. In researching this I have concluded that I need to use an ItemsControl with the ItemsPanelTemplate declared as a Canvas, as in

<ItemsControl>
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
         <Canvas/>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

I have also figured out that I need to put something (not sure what) in the ItemTemplate, like so . . .

  <ItemsControl.ItemTemplate>
     <DataTemplate>
         <!--  Don't know what goes here -->
     </DataTemplate>
  </ItemsControl.ItemTemplate>

My Question

Can someone advise me on what to put in the DataTemplate so that I can bind to my ViewModel and have the ViewModel draw either text (any rotation, any font, etc.), a line, an arc, a bezier, a shape - - - whatever I need depending on the various kinds of elements in my bound collection?

My guess is that is should be a System.Windows.FrameworkTemplate, but I am still trying to figure out how to use it, and it is slow-going. Or maybe ContentControl and Presenter?

References

How to convert X/Y position to Canvas Left/Top properties when using ItemsControl

How can I position ViewModels in an ItemsControl

Is it possible to bind a Canvas's Children property in XAML? Note: See the second answer on this one.

1

1 Answers

2
votes

There are different ways.

You can switch DataTemplates based on the selector.

public class ImgStringTemplateSelector : DataTemplateSelector
{
  public DataTemplate ImageTemplate { get; set; }
  public DataTemplate StringTemplate { get; set; }

  public override DataTemplate SelectTemplate(object item,
    DependencyObject container)
  {
    String path = (string)item;
    String ext = System.IO.Path.GetExtension(path);
    if (System.IO.File.Exists(path) && ext == ".jpg")
      return ImageTemplate;
    return StringTemplate;
  }

YOu can reference to it through ItemsPanel ItemTemplateSelector. Sch as ItemTemplateSelector="{StaticResource ImgTemplateSelector}". In that, you choose what template to return.

You can return Line template, Arc template, etc.. It's pretty easy.

The other trick is you can have base class DrawingObject and derive from it. Such as ArcObj : DrawingObject,

later you just add

<DataTemplate Datatype="{x:Type ArcObj"}>
<Arc Canvas.Left="{BInding X}", Canvas.Top="{Binding Y}" />
</DataTemplate>

and so on.