Constructing GoDiagram with two different models

I am evaluting GoSilverlight. As we can see from the Demo, almost in each example a model is being defined as follows.

// set up an initial model for the Diagram
var model = new GraphLinksModel<MyNodeData, String, String, MyLinkData>();
for this an xml file is defined with same kind of nodes (like GateData, Wire Data..but here these two are related)
I have a question here. If my model is to be built with two different kind of nodes, is it possible though GoDiagram? If so, please give me little insight to achive the same.
Thanks & Regards
Padma

GoXam supports only a single model for each Diagram. If you want to use multiple node data classes, you can – just use the common base Type as the first type parameter of the model. If necessary this can be Object.

However, I hope it is clear that doing so does lose some of the advantages of using generic classes, particularly type safety.

Could you be little elaborate how can we have different models defined and load the diagram with them?

I would also like to know the significant advantage of this modeling concept in GoXam. Please provide me with some concerned reading/reference on this.
Thanks & Regards
Padma

I can create a sample for you demonstrating the use of different models and different data classes.

There is a lot of literature about model-view-controller and model-view-viewmodel.

The basic point is that GoXam models implement the abstractions of graphs (both link relationships and group-member relationships) using almost any in-memory data. Of course it’s better when the data class(es) implement standard interfaces such as INotifyPropertyChanged and ICloneable. And we offer some standard data classes that have some additional features, such as support for reading/writing XML.

This abstraction frees up the design and implementation of the visual representation of the diagram. The same piece of data can be displayed in drastically different ways depending on the DataTemplate used.

Diagram controls that do not provide this layer cause applications to know a lot more about the visual implementation. This makes it harder to maintain and change in the future as requirements evolve.

A closely related issue is support for data-binding and templating and styling. In the XAML world (both Silverlight and WPF) every control is expected to fully support all three. We designed GoXam with those issues in mind.

You may have noticed that our GoDiagram controls for WinForms and WebForms were designed in a more traditional manner. When we decided to offer controls for WPF and later Silverlight, we knew that we had to completely change the design philosophy in order to provide the best features and integration into the application. In retrospect I’m glad we did.

OK, here’s a demo (for Silverlight) that uses three separate but related node data classes and three corresponding DataTemplates.

There’s also an initial model which is remembered in an internal property so that it can be shown again by the first Button. And the second Button creates and shows a different model with a varying number of nodes, each time you click.

[code]
<UserControl.Resources>










<DataTemplate x:Key="AstronautTemplate">
  <Border BorderBrush="Silver" BorderThickness="3" CornerRadius="5" Padding="5" Background="White">
    <StackPanel>
      <TextBlock Text="{Binding Path=Data.Text}" FontWeight="Bold" FontSize="12"/>
      <TextBlock Text="Astronaut" FontStyle="Italic" FontSize="10" />
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="Mass: " />
        <TextBlock Text="{Binding Path=Data.Mass}" />
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="Weight: " />
        <TextBlock Text="{Binding Path=Data.CurrentWeight}" />
      </StackPanel>
    </StackPanel>
  </Border>
</DataTemplate>

<DataTemplate x:Key="RaceCarDriverTemplate">
  <Border BorderBrush="Red" BorderThickness="3" Padding="5" Background="White">
    <StackPanel>
      <Border Background="DarkBlue">
        <TextBlock Text="{Binding Path=Data.Text}" FontWeight="Bold" FontSize="12" Foreground="White" />
      </Border>
      <TextBlock Text="Race Car Driver" FontStyle="Italic" FontSize="10" />
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="Weight: " />
        <TextBlock Text="{Binding Path=Data.Mass}" />
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="Speed: " />
        <TextBlock Text="{Binding Path=Data.CurrentSpeed}" />
      </StackPanel>
    </StackPanel>
  </Border>
</DataTemplate>

</UserControl.Resources>

[/code]

[code]using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Northwoods.GoXam;
using Northwoods.GoXam.Model;

namespace SilverlightApplication1 {
public partial class MultiDataModel : UserControl {
public MultiDataModel() {
InitializeComponent();

  // support three categories of templates for nodes
  var dtd = new DataTemplateDictionary();
  dtd.Default = Diagram.FindResource<DataTemplate>(myDiagram, "PersonTemplate");
  dtd.Add("Astronaut", Diagram.FindResource<DataTemplate>(myDiagram, "AstronautTemplate"));
  dtd.Add("RaceCarDriver", Diagram.FindResource<DataTemplate>(myDiagram, "RaceCarDriverTemplate"));
  myDiagram.NodeTemplateDictionary = dtd;

  // create a trivial model holding one instance of each node data class
  var model1 = new GraphModel<Person, String>();
  model1.NodesSource = new List<Person>() {
    new Person() { Key="1", Category="", Text="Joe Random", Mass=50 },
    new Astronaut() { Key="2", Category="Astronaut", Text="Joe Wright", Mass=50, CurrentWeight=0.01 },
    new RaceCarDriver() { Key="3", Category="RaceCarDriver", Text="Fast Joe", Mass=50, CurrentSpeed=203 },
  };
  this.Model1 = model1;

  // start off showing this model
  myDiagram.Model = this.Model1;
}

internal GraphModel<Person, String> Model1 { get; set; }

private void Button1_Click(object sender, RoutedEventArgs e) {
  myDiagram.Model = this.Model1;
}

private void Button2_Click(object sender, RoutedEventArgs e) {
  var model2 = new GraphModel<Person, String>();
  model2.NodesSource = GeneratePeople();
  myDiagram.Model = model2;
}

private IList<Person> GeneratePeople() {
  var people = new List<Person>();
  Random rand = new Random();
  int num = rand.Next(10) + 3;
  for (int i = 0; i < num; i++) {
    Person p;
    switch (rand.Next(3)) {
      case 1: p = new Astronaut() { Category="Astronaut" }; break;
      case 2: p = new RaceCarDriver() { Category="RaceCarDriver" }; break;
      default: p = new Person() { Category="" }; break;
    }
    p.Key = i.ToString();
    p.Text = "Person #" + i.ToString();
    p.Mass = rand.Next(100);
    people.Add(p);
  }
  return people;
}

}

public class Person : GraphModelNodeData {
public double Mass {
get { return _Mass; }
set {
if (_Mass != value) {
double old = _Mass;
_Mass = value;
RaisePropertyChanged(“Mass”, old, value);
}
}
}
private double _Mass;
}

public class Astronaut : Person {
public double CurrentWeight {
get { return _CurrentWeight; }
set {
if (_CurrentWeight != value) {
double old = _CurrentWeight;
_CurrentWeight = value;
RaisePropertyChanged(“CurrentWeight”, old, value);
}
}
}
private double _CurrentWeight;
}

public class RaceCarDriver : Person {
public double CurrentSpeed {
get { return _CurrentSpeed; }
set {
if (_CurrentSpeed != value) {
double old = _CurrentSpeed;
_CurrentSpeed = value;
RaisePropertyChanged(“CurrentSpeed”, old, value);
}
}
}
private double _CurrentSpeed;
}
}[/code]

Oh, for an example of the same data being shown simultaneously in fairly different manners in different Diagrams, using different DataTemplates, take a look at the UpdateDemo sample.

Thanks a ton for such a good and quick support.

I have one more question here. Since we can different models as mentioned, can we also have links between them. I mean can we have a Graph link model for the example given by you?
Thanks & Regards
Padma

I got how to have links in the example you provided.

Thanks so much.
Regards
Padma

Sorry I didn’t make that clear. For exposition purposes I avoided link relationships and grouping relationships.

For other people reading this topic, you just have to provide in the node data the references to other nodes, such as:

      model1.NodesSource = new List() {
        new Person() { Key="1", Category="", Text="Joe Random", Mass=50, ToKeys=new List() { "2", "3" } },
        new Astronaut() { Key="2", Category="Astronaut", Text="Joe Wright", Mass=50, CurrentWeight=0.01 },
        new RaceCarDriver() { Key="3", Category="RaceCarDriver", Text="Fast Joe", Mass=50, CurrentSpeed=203 },
      };

If you need more flexibility with links than what GraphModel provides, just replace it with GraphLinksModel everywhere in the code, and supply a LinksSource for all of the link data.

FYI, I show a different way of organizing all of the DataTemplates and data classes in this post.