I’m trying to dynamically (programmatically) change the appearance of a node, and i don’t understand how i can do this.
i would like to drag a node from the palette to the diagram and change its appearance once it is dropped on the diagram. The node in the palette have a simple appearance and i would like the dropped node to have a more complex one.
At the moment, i have tried to define 2 dataTemplates in my NodeTemplateDictionnary, which corresponds to 2 categories, and change the node category during the OnNodeAdded() method of my custom PartManager. But that do not force the node to redraw with its new appearance. i presume only change the category isn’t sufficient.
I also would like to be able change the appearance on other types of interaction between the UI and the user, such as a click on a button or almost any kind of event.
If you always want one appearance in one diagram (e.g. the Palette) and another appearance in another diagram (e.g. the main Diagram), then just use different DataTemplates. In this case you’re not actually replacing the template for a node (or link) dynamically.
If you are using version 1.1, it supports dynamically changing the Category for a node data (or link data). Basically the PartManager detects the …Model.Changed event announcing ModelChange.NodeCategoryChanged, and just removes from the Diagram the Node for a particular node data and then creates a new Node using a different DataTemplate from the DataTemplateDictionary.
If you are using version 1.0, you can do this work yourself. In 1.0 the models do not keep track of changes to the Category for any data, so naturally the PartManager doesn’t know about changing categories. You’ll need to call PartManager.RemoveNodeForData and then AddNodeForData.
Oh, and regarding changing the appearance when the user does some mouse events in a node, that doesn’t really involve GoXam at all. Everything you’ve learned about Silverlight or WPF programming still applies inside a node.
If i need to remove the node and create a new copy of it, with a different dataTemplate means that there is no way to change the appearance of a node on the fly (And get its appearance from a dataTemplate if possible) ?
I not really interrested in removing and recreating a node because, in my current implementation, my nodes are binded to databases record and removing a node imply, remove a record from database.
I have started to learn Silverlight with this GoXam projet, so i’m a newbie in Silverlight programming.
All right, so this "node switch"will not affect the model, only what we saw in the diagram.
In fact, i need to replace the Node object with a new one using the same Node.Data object, and this using the PartManager.RemoveNodeForData() and PartManager.AddNodeForData() methods. Is that right ?
End of the day in France, so i have to go. I will try this tomorrow morning and let you know…
I tried something this morning but I can’t figure out where/when do I need to change the category attribute.
Do I need to change the category in the nodeData object or in the Node object ?
Which one is used to redraw the node ? Where does the category attribute is read from when the new node is drawn ?
I tried to do the “node switch” in the OnNodeAdded() method of my custom PartManager class, like so :
Protected Overrides Sub OnNodeAdded(ByVal node As Northwoods.GoXam.Node)
MyBase.OnNodeAdded(node)
Try
If CType(node.Data, NodeGoXam).Category = "Standard" Then
Me.RemoveNodeForData(node.Data, ApplicationSharedData.Model)
CType(node.Data, NodeGoXam).Category = "StandardCas1"
Me.AddNodeForData(node.Data, ApplicationSharedData.Model)
End If
Catch ex As Exception
End Try
End Sub
I would like the new node to be drawn with the appearance defined by my DataTemplate corresponding to category “StandardCas1”.
I don’t think you want to modify your data nor do you want to add or remove nodes in an override of PartManager.OnNodeAdded (or any of the other similar overridable methods). Perhaps we should have made that clearer in the documentation.
Basically what your code is doing is changing the Category of every “Standard” node data that you have added to your model to be “StandardCas1”. That means you can’t have any “Standard” category nodes at all in your diagram.
Well i also tried this, but the only result I got is that the node disappears from the diagram (Because of RemoveNodeForData). When the next Layout happens, the node reappears in the top left corner of the diagram (Because of the AddNodeForData), but the appearance is still the same. So, the node seems to be redrawn using the same dataTemplate.
Private Sub Affectation_MouseLeftButtonDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
Dim nodeData As NodeGoXam = TryCast(Part.FindAncestor(Of Node)(TryCast(sender, UIElement)).Data, NodeGoXam)
myDiagram.PartManager.RemoveNodeForData(nodeData, ApplicationSharedData.Model)
nodeData.Category = "Standard"
myDiagram.PartManager.AddNodeForData(nodeData, ApplicationSharedData.Model)
myDiagram.LayoutDiagram()
End Sub
In this case, i tried to change a “StandardCas1” category node appearance to a “Standard” one.
I’m obviously missing something…
Which method decide which dataTemplate will be use to render a node ?
Actually, I’m the one who missed something in getting this to work in version 1.0.
I modified the FlowChart sample by adding a Button and this event handler:
private void Button_Click(object sender, RoutedEventArgs e) {
if (myDiagram.SelectedNode != null) {
MyNodeData data = myDiagram.SelectedNode.Data as MyNodeData;
if (data != null) {
myDiagram.StartTransaction("change category");
myDiagram.PartManager.RemoveNodeForData(data, myDiagram.Model);
switch (data.Category) {
case "Start": data.Category = "Standard"; break;
case "Standard": data.Category = "End"; break;
case "End": data.Category = "Start"; break;
}
myDiagram.PartManager.AddNodeForData(data, myDiagram.Model);
myDiagram.CommitTransaction("change category");
}
}
}
This is exactly as I said before.
What I forgot is that the v1.0 models assume that the category never changes. In order for the above data change to have any effect, override the PartManager.FindCategoryForNode method:
public class MyPartManager : PartManager {
protected override string FindCategoryForNode(object nodedata, IDiagramModel model, bool isgroup, bool islinklabel) {
MyNodeData data = nodedata as MyNodeData;
if (data != null) return data.Category;
return base.FindCategoryForNode(nodedata, model, isgroup, islinklabel);
}
}
And install the new PartManager by setting:
myDiagram.PartManager = new MyPartManager();