I'm evaluating telerik controls now, and my company will purchase in this month.
I want to know how to save multiple diagram pages with MVVM. (You can see this scenario in a attached screenshot)
Your document and sample is only showing "RadDiagram.Save()" to save a diagram, but my application is generating a diagram dynamically for each tab content.
In this case, SerializableGraphSource doesn't know what diagram is connected with it.
And a diagram instance will be destroyed and recreated when tab control selection is changed.
Should I make my own save/load functions for this?
I would appreciate if you give me some advice.
Thank you.
4 Answers, 1 is accepted
Unfortunatelly, we don't have this functionality built-in. So I would have a ViewModel that has a collection of SerializableGraphSourceBase - this will serve my TabControl ItemsSource. And then I think it shouldn't be very hard to implement serialization of collection of SerializableGraphSourceBase objects.
On a side note our RadTabControl can preserve its content on tab change - there is property called IsContentPreserved. If it's true the content won't be destroyed when you change tab.
Please let us know if you need further assistance on implementing the save/load functionality.
Miro Miroslavov
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
Thank you for your reply.
I have another question.
1. I bound Position of a shape with TwoWay as follows.
<
Style
x:Key
=
"imageShapeStyle"
TargetType
=
"{x:Type telerik:RadDiagramShape}"
>
<
Setter
Property
=
"Position"
Value
=
"{Binding Position, Mode=TwoWay}"
/>
<
Setter
Property
=
"StrokeThickness"
Value
=
"0"
/>
<
Setter
Property
=
"ZIndex"
Value
=
"1"
/>
<
Setter
Property
=
"Background"
Value
=
"Transparent"
/>
<
Setter
Property
=
"Visibility"
Value
=
"{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}, Mode=TwoWay}"
/>
<
Setter
Property
=
"AllowDrop"
Value
=
"False"
/>
<
Setter
Property
=
"HorizontalContentAlignment"
Value
=
"Center"
/>
<
Setter
Property
=
"VerticalContentAlignment"
Value
=
"Center"
/>
<
Setter
Property
=
"ContentTemplate"
Value
=
"{StaticResource imageShapeContentTemplate}"
/>
<
Setter
Property
=
"EditTemplate"
Value
=
"{StaticResource imageShapeEditTemplate}"
/>
</
Style
>
2. I made my own ItemViewModel for a shape binding
public
class
ItemViewModel : ViewModelBase
{
private
bool
isVisible;
public
bool
IsSelected {
get
;
set
; }
public
bool
IsValid {
get
;
set
; }
private
string
text;
private
int
textSize;
private
Point position;
public
ItemViewModel()
{
IsValid =
true
;
IsVisible =
true
;
}
public
Point Position
{
get
{
return
this
.position;
}
set
{
if
(
this
.position != value)
{
this
.position = value;
Debug.WriteLine(
"position changed...."
);
this
.OnPropertyChanged(
"Position"
);
}
}
}
3. When I drag a shape in a diagram, Position property is changed well.
But when I cut/copy and paste a shape in a diagram, a pasted shape does not change it's Position property. I don't know why this is happening.
I implemented SealizeNode(), DeserializeNode() function as follows.
public
class
DiagramGraphSource : IObservableGraphSource, ISerializableGraphSource
{
private
readonly
ObservableCollection<NodeViewModel> items =
new
ObservableCollection<NodeViewModel>();
private
readonly
ObservableCollection<LinkViewModel> links =
new
ObservableCollection<LinkViewModel>();
public
LinkType LinkType {
get
;
set
; }
public
NetworkDiagram DiagramView {
get
;
set
; }
public
ObservableCollection<NodeViewModel> InternalItems
{
get
{
return
this
.items; }
}
public
ObservableCollection<LinkViewModel> InternalLinks
{
get
{
return
this
.links; }
}
public
IEnumerable Items
{
get
{
return
this
.items; }
}
public
IEnumerable<ILink> Links
{
get
{
return
this
.links; }
}
public
DiagramGraphSource()
{
}
public
object
CreateNode(IShape shape)
{
Debug.WriteLine(
"create node.."
);
return
new
NodeViewModel();
}
public
void
AddNode(
object
node)
{
var item = node
as
NodeViewModel;
Debug.WriteLine(
"add node.."
+item.Position.ToString());
//Point point = new Point(0,0);
//item.Position = point;
items.Add(item);
}
public
bool
RemoveNode(
object
node)
{
Debug.WriteLine(
"reomove node.."
);
var item = node
as
NodeViewModel;
bool
result = items.Remove(item);
item.IsValid =
false
;
item =
null
;
return
result;
}
public
void
AddLink(ILink link)
{
var linkItem = link
as
LinkViewModel;
/*
NodeViewModel source = linkItem.Source;
NodeViewModel target = linkItem.Target;
if (source != null && target != null)
{
Debug.WriteLine("connection established...");
}
*/
UpdateLinkStyle(linkItem);
links.Add(linkItem);
}
public
bool
RemoveLink(ILink link)
{
var linkItem = link
as
LinkViewModel;
bool
result = links.Remove(linkItem);
linkItem.IsValid =
false
;
linkItem =
null
;
return
result;
}
public
ILink CreateLink(
object
source,
object
target)
{
var itemSource = source
as
NodeViewModel;
var itemTarget = target
as
NodeViewModel;
var linkItem =
new
LinkViewModel();
UpdateLinkStyle(linkItem);
linkItem.Source = itemSource;
linkItem.Target = itemTarget;
return
linkItem;
}
public
string
GetNodeUniqueId(NodeViewModel node)
{
return
node.UID;
}
public
void
SerializeLink(ILink link, SerializationInfo info)
{
}
public
ILink DeserializeLink(IConnection connection, SerializationInfo info)
{
return
null
;
}
public
void
SerializeNode(
object
oNode, SerializationInfo info)
{
Debug.WriteLine(
"serialize node.."
);
NodeViewModel node = oNode
as
NodeViewModel;
SerializeNodeInfo(node, info);
if
(node
is
ImageNodeViewModel)
{
ImageNodeViewModel imageNode = node
as
ImageNodeViewModel;
info[
"Image"
] = imageNode.Image;
}
}
public
object
DeserializeNode(IShape shape, SerializationInfo info)
{
Debug.WriteLine(
"deserialize node.."
);
if
(info[
"PropertyType"
].ToString() ==
typeof
(NetworkCameraProperty).ToString())
{
CameraNodeViewModel camera =
new
CameraNodeViewModel();
camera.Image = info[
"Image"
].ToString();
XmlSerializer xmlSerializer = DataManager.Instance.xmlSerializer_NetworkCameraProperty;
TextReader reader =
new
StringReader(info[
"Property"
].ToString());
NetworkCameraProperty cameraProperty = xmlSerializer.Deserialize(reader)
as
NetworkCameraProperty;
camera.Property = cameraProperty;
DeserializeNodeInfo(camera, info);
return
camera;
}
else
if
(info[
"PropertyType"
].ToString() ==
typeof
(NvrProperty).ToString())
{
NvrNodeViewModel nvr =
new
NvrNodeViewModel();
nvr.Image = info[
"Image"
].ToString();
XmlSerializer xmlSerializer = DataManager.Instance.xmlSerializer_NvrProperty;
TextReader reader =
new
StringReader(info[
"Property"
].ToString());
NvrProperty nvrProperty = xmlSerializer.Deserialize(reader)
as
NvrProperty;
nvr.Property = nvrProperty;
DeserializeNodeInfo(nvr, info);
return
nvr;
}
else
if
(info[
"PropertyType"
].ToString() ==
typeof
(SwitchProperty).ToString())
{
SwitchNodeViewModel sw =
new
SwitchNodeViewModel();
sw.Image = info[
"Image"
].ToString();
XmlSerializer xmlSerializer = DataManager.Instance.xmlSerializer_SwitchProperty;
TextReader reader =
new
StringReader(info[
"Property"
].ToString());
SwitchProperty swProperty = xmlSerializer.Deserialize(reader)
as
SwitchProperty;
sw.Property = swProperty;
DeserializeNodeInfo(sw, info);
return
sw;
}
else
if
(info[
"PropertyType"
].ToString() ==
typeof
(CmsProperty).ToString())
{
CmsNodeViewModel cms =
new
CmsNodeViewModel();
cms.Image = info[
"Image"
].ToString();
XmlSerializer xmlSerializer = DataManager.Instance.xmlSerializer_CmsProperty;
TextReader reader =
new
StringReader(info[
"Property"
].ToString());
CmsProperty cmsProperty = xmlSerializer.Deserialize(reader)
as
CmsProperty;
cms.Property = cmsProperty;
DeserializeNodeInfo(cms, info);
return
cms;
}
else
if
(info[
"PropertyType"
].ToString() ==
typeof
(SsmProperty).ToString())
{
SsmNodeViewModel ssm =
new
SsmNodeViewModel();
ssm.Image = info[
"Image"
].ToString();
XmlSerializer xmlSerializer = DataManager.Instance.xmlSerializer_SsmProperty;
TextReader reader =
new
StringReader(info[
"Property"
].ToString());
SsmProperty ssmProperty = xmlSerializer.Deserialize(reader)
as
SsmProperty;
ssm.Property = ssmProperty;
DeserializeNodeInfo(ssm, info);
return
ssm;
}
else
{
Debug.WriteLine(
"why here.."
);
NodeViewModel node =
new
NodeViewModel();
DeserializeNodeInfo(node, info);
return
node;
}
}
private
void
SerializeNodeInfo(NodeViewModel node, SerializationInfo info)
{
// info["UID"] = node.UID;
info[
"Width"
] = node.Width;
info[
"Height"
] = node.Height;
info[
"TextSize"
] = node.TextSize;
info[
"Position"
] = node.Position.ToInvariant();
info[
"IsVisible"
] = node.IsVisible;
XmlSerializer xmlSerializer =
null
;
if
(node
is
CameraNodeViewModel)
xmlSerializer = DataManager.Instance.xmlSerializer_NetworkCameraProperty;
else
if
(node
is
NvrNodeViewModel)
xmlSerializer = DataManager.Instance.xmlSerializer_NvrProperty;
else
if
(node
is
CmsNodeViewModel)
xmlSerializer = DataManager.Instance.xmlSerializer_CmsProperty;
else
if
(node
is
SsmNodeViewModel)
xmlSerializer = DataManager.Instance.xmlSerializer_SsmProperty;
else
if
(node
is
SwitchNodeViewModel)
xmlSerializer = DataManager.Instance.xmlSerializer_SwitchProperty;
if
(xmlSerializer !=
null
)
{
StringWriter textWriter =
new
StringWriter();
xmlSerializer.Serialize(textWriter, node.Property);
info[
"PropertyType"
] = node.Property.ToString();
info[
"Property"
] = textWriter.ToString();
}
}
private
void
DeserializeNodeInfo(NodeViewModel node, SerializationInfo info)
{
// node.UID = info["UID"].ToString();
node.Width =
int
.Parse(info[
"Width"
].ToString());
node.Height =
int
.Parse(info[
"Height"
].ToString());
node.TextSize =
int
.Parse(info[
"TextSize"
].ToString());
node.Position = Utils.ToPoint(info[
"Position"
].ToString()).Value;
node.IsVisible =
bool
.Parse(info[
"IsVisible"
].ToString());
//node.Position = new Point(0, 0);
}
private
void
UpdateLinkStyle(LinkViewModel link)
{
switch
(LinkType)
{
case
LinkType.Network10Mbps:
link.MainColor =
"#A8A8A8"
;
link.Text =
"10Mbps"
;
break
;
case
LinkType.Network100Mbps:
link.MainColor =
"#000000"
;
link.Text =
"100Mbps"
;
break
;
case
LinkType.Network1Gbps:
link.MainColor =
"#09BA00"
;
link.Text =
"1Gbps"
;
break
;
case
LinkType.Network10Gbps:
link.MainColor =
"#0021F7"
;
link.Text =
"10Gbps"
;
break
;
}
}
}
The problem occurs because the Serialization by default is serializing the Position property and when desirializing it sets the Position property of the new shape to the appropriate value which removes the binding.
There are several ways to prevent this and the easiest for you is to discard the position property in the serialization:
public void SerializeNode(object oNode, SerializationInfo info)
{
Debug.WriteLine("serialize node..");
info[SerializationConstants.Position] = string.Empty;
Any of the mentioned tricks should work for you.
Hope this helps. Regards,
Miro Miroslavov
Telerik
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
Thank you very much for your help.
Now I solved this problem.