This project has moved and is read-only. For the latest updates, please go here.

Two ways to assign model to shape

Nov 2, 2012 at 4:01 PM
Edited Nov 2, 2012 at 7:02 PM

Hi,

What is the difference between the following 2 ways of creating shape-model pair:

Way #1:
(when used, each new shape automatically gets a new model object assigned)

Template template = this.project1.Repository.GetTemplate("MyShape");
MyModel modelObj = (MyModel)this.project1.ModelObjectTypes["MyShapeModel"].CreateInstance();
// Assign model object to template shape
template.Shape.ModelObject = modelObj;
// Add model object and update template
this.project1.Repository.Insert(modelObj);
this.project1.Repository.Update(template);
// Map terminals (or our shape looses connectability - see http://nshape.codeplex.com/discussions/399871):
int n = 0;
foreach (ControlPointId id in template.Shape.GetControlPointIds(ControlPointCapabilities.Connect))
{
    template.MapTerminal(modelObj.Terminals[n++], id);
}

Way #2:
(when used, creates shape with model successfully, but crashes with CachedRepositoryException when I start moving shape)

MyShape ps = this.project1.ShapeTypes["MyShape"].CreateInstance() as MyShape;
ps.ModelObject = this.project1.ModelObjectTypes["MyShapeModel"].CreateInstance();
this.display1.Diagram.Shapes.Add(ps);

What are the pros and cons of each way?

Thank You.

[UPDATE] When using the 1st way, I noticed a strange effect: changes I make in a model of one of my existing shapes, are somehow propagated into the model used to create new shapes (of the same type). For example, I created a shape of type "MyShape" and placed it on the diagram. Model object of this shape is of the "MyShapeModel" type, and this type has property Description, and this property's value is being drawn on the shape. I set this property to "abc123" in the "Model" PropertyGrid and immediately see this text is drawn on the shape. Excellent. After that I pick up new "MyShape" shape from the toolbox and drag it onto the diagram; while doing this I see that the same text ("abc123") is drawn on the preview shape. When at last I place this second shape on the diagram and inspect its model, I see this text as the Description property's value. Why does this happen?

Nov 5, 2012 at 2:16 PM

Regarding Way 1:
You should call project.Reopsitory.Update(template) after adding the terminal mappings. Afterwards, you should use the template for creating shapes. I would recomend this way.

Regarding Way 2:
This is a very low level approach. It's easy to forget something create shapes and models this way.

 

Regarding the issue described in the update:
Could you provide some code or a small demo (send to support(at)dataweb(dot)de ) where I can see/reproduce the issue?

Nov 6, 2012 at 5:03 AM
KurtHolzinger wrote:

Regarding the issue described in the update:
Could you provide some code or a small demo (send to support(at)dataweb(dot)de ) where I can see/reproduce the issue?

While preparing the demo, I fixed this issue myself :) well, it often happens so :) the reason was that MyShapeModel.Description property was just a map to MyShapeModel.ComplexObject.Description property, and in the MyShapeModel.Clone() method I forgot to clone the ComplexObject property: instead I was simply assigning (clone.ComplexObject = this.ComplexObject), so the clone pointed to the same in-memory object, and of course MyShapeModel.Description pointed to the same string.

Thank you for your time.

PS: it's been a long time as I wanted to ask you this question, and now it seems to be a good time for this :) why do you place an instantiated model object into the repository (as well as assign it to template.Shape.ModelObject) and later use it with all shapes (via cloning) - instead of just associating assembly-qualified type name of the model with the corresponding shape? what is the benefit of your approach? And why do you clone everything (shape + its model) while moving shape? why not just... move it?! :)

Nov 20, 2012 at 8:52 AM
Edited Nov 20, 2012 at 8:52 AM
Comanche wrote:
it's been a long time as I wanted to ask you this question, and now it seems to be a good time for this :) why do you place an instantiated model object into the repository (as well as assign it to template.Shape.ModelObject) and later use it with all shapes (via cloning) - instead of just associating assembly-qualified type name of the model with the corresponding shape? what is the benefit of your approach?

There are 2 main reasons why the model objects have to be instantiated:

  1. The model objects have internal states that are not equal for all model objects
  2. In order to use property mappings, you need an instantiated model object where you can set the property (that is represented by the shape)

In addition to that, we tried to avoid .NET reflection where ever it is possible because reflection is quite expensive in terms of performance.

 

Comanche wrote:
And why do you clone everything (shape + its model) while moving shape? why not just... move it?! :)
  • No preview of the drag action's result
  • When moving the shape directly, you have to ensure that all dragged shapes and all shapes connected to the dragged shapes are moved back to exactly the same position as soon as the user aborts the drag action. This is problematic especially when moving rotated shapes because of rounding errors.
  • As the Tool is moving only clones of the shape(s), the framework does not have to care about what the tool does with the preview shapes.