2

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.

Community
  • 1
  • 1
philologon
  • 2,093
  • 4
  • 19
  • 35

1 Answers1

2

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.

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78
  • Thank you ChrisDD. I am currently working on implementing this suggestion. I found the exact same sample code (of your first suggestion) at http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector Aren't you supposed to give a reference to the place where you copied the code from? Maybe you did, but I don't see it. – philologon Oct 08 '12 at 22:06
  • The link to the article from WebArchive - http://web.archive.org/web/20121214030728/http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector (in case someone wants more information) – AntonK Jul 28 '17 at 23:57