/// <summary>
/// Serialize all the nodes of this tree to the stream provided, using the formatter provided.
/// </summary>
/// <param name="stream">The stream to serialize to.</param>
/// <param name="formatter">The formatter used to serialize.</param>
/// <summary>
/// Recreate this tree from a serialized version.
/// </summary>
/// <param name="stream">the stream that contains the serialized tree.</param>
/// <param name="formatter">the formatter used to desrialize the stream.</param>
public
: void Deserialize(Stream^ stream, IFormatter^ formatter) { // Clear our tree: this->Nodes->Clear(); SerializableTreeView^ temp = (SerializableTreeView^ )formatter->Deserialize(stream); if (temp != nullptr) {
// copy the nodes from the temp to our tree:
for each(System::Windows::Forms::TreeNode^ node in temp->Nodes) { this->Nodes->Add((System::Windows::Forms::TreeNode^)node->Clone()); }
This code has a problem, when I serialize a tree with images, after the deserialization all the ImageIndex are equal with -1, in fact the only information preserved is the Text field.
Thanks for the code! I'm a bit of a beginner, though, and am not sure how to use this code - how does the contructor's inputs (SerializationInfo info, StreamingContext context) reference an existing TreeView Does anyone have an example of how one would take an existing TreeView and make it serializable using this class
I want to ask do you have a version of serialize a ListView in Visual C++
Below is my effort, I use a CSV file to save all the items and a conventional way of deleting the file, create a new one after the item in ListView is deleted, reading files and display it again to listView, but it also don't work.
I was confused and don't know what to do to read and write a listView to a CSV file which is a very long and time wasting process.
I have read the code of serialize with TreeView but I also need to serialize with listView.
Here is the code I've tried:
private: System::Void listView1_KeyDown(System:bject^ sender, System::Windows::Forms::KeyEventArgs^ e) { String^ fileToDel="C:\\Chris\\Testing\\Assignment1\\data.txt"; String^ fileToReplace="C:\\Chris\\Testing\\Assignment1\\data.txt"; String^ backupfileToReplace="C:\\Chris\\Testing\\Assignment1\\backup.bak"; if (e->KeyCode == Keys:elete) //delete listView di treeView juga dihapus dan sebaliknya. { //delete listView items before physically. listView1->Items->RemoveAt(idxlist); listView1->Refresh(); //backup pada waktu listView di-DEL. //coding di file "Backup pada waktu listView di del.txt" //update file String^ path = "C:\\Chris\\Testing\\Assignment1\\data.txt";
// This text is added only once to the file. // Create a file to write to. StreamWriter^ sw = File::CreateText( path ); try { //save all listView items before cleared. ListView::ListViewItemCollection^ list = this->listView1->Items; System::Collections::IEnumerator^ myEnum = list->GetEnumerator(); int i = 0; while ( myEnum->MoveNext() ) { ListViewItem^ item = safe_cast<ListViewItem^>(myEnum->Current); ListViewItem::ListViewSubItemCollection^ subitem = item->SubItems; System::Collections::IEnumerator^ myEnum1 = subitem->GetEnumerator(); //MessageBox:how(item->Text); //MessageBox:how(myEnum1->Current->ToString()); /*while ( myEnum1->MoveNext() ){ ListViewItem:ubItems sit = safe_cast<ListViewItem::ListViewSubItem^>(myEnum1->Current); MessageBox:how(); }*/ //int i=0; //while ( myEnum1->MoveNext() ){ //Writing to CSV format from listView items. //company name from String variable "nodecomp" on Form1 which get node name selected. //if (i==0) { //company name sw->Write(item->Text); sw->Write(","); //} //else if (i==1) { //employee name sw->Write(item->Text); sw->Write(","); //} //employee age //else if (i==2) { sw->Write(item->Text); sw->Write(","); //} //gender //else if (i==3) { sw->Write(item->Text); sw->Write(","); //} //address //else if (i==4) { sw->Write(item->Text); sw->Write(","); //} //city //else if (i==5) { sw->Write(item->Text); sw->Write(","); //} //zip //else if (i==6) { sw->Write(item->Text); sw->Write(","); //} //phone //else if (i==7) { sw->WriteLine(item->Text); //} i++; //Writing to CSV Format from listView items. //} //while myEnum1 //count++;
Well, it's apparently not a good idea to serialize a UI component like a tree view, instead, you should serialize a data structure that represents the tree view.
The problem with serializing a TreeView (or any other UI component) is that if you have to deserialize it, you have to remove the old version of your tree view and replace it with the deserialized version. Which is anoying because if you created your form with the form designer in VS 2005, then you have to syncronize all your settings with the deserialized tree. This is really anoying during design & development phase because you may make changes to your tree's properties in the designer (at design time), but forget to add those changes to your deserialized tree (at runtime). Anyways, despite the drawbacks, I created a serializable/deserializabe tree view. The advantage with my tree view is that it doesn't destroy the tree itself, just the node structure, so you don't have to worry about setting all the properties on the treeview control itself. The disadvantage is, it has to create a temporary tree view and copy all the nodes to the current tree during deserialization.
Here is the code:
using System; using System.IO; using System.Runtime.Serialization; using System.Windows.Forms;
namespace AssetBrowserControl {
/// <summary> /// Summary description for SerializableTreeView. /// </summary> /// [Serializable] public class SerializableTreeView : TreeView, ISerializable {
public SerializableTreeView() : base() { }
public SerializableTreeView(SerializationInfo info, StreamingContext context) : this() {
SerializationInfoEnumerator infoEnumerator = info.GetEnumerator(); while (infoEnumerator.MoveNext()) {
public void GetObjectData(SerializationInfo info, StreamingContext context) {
foreach(TreeNode node in this.Nodes) {
info.AddValue(node.FullPath, node);
}
}
/// <summary> /// Serialize all the nodes of this tree to the stream provided, using the formatter provided. /// </summary> /// <param name="stream">The stream to serialize to.</param> /// <param name="formatter">The formatter used to serialize.</param> public void Serialize(Stream stream, IFormatter formatter) {
formatter.Serialize(stream, this);
}
/// <summary> /// Recreate this tree from a serialized version. /// </summary> /// <param name="stream">the stream that contains the serialized tree.</param> /// <param name="formatter">the formatter used to desrialize the stream.</param> public void Deserialize(Stream stream, IFormatter formatter) {
// Clear our tree: this.Nodes.Clear(); SerializableTreeView temp = formatter.Deserialize(stream) as SerializableTreeView; if (temp != null) {
// copy the nodes from the temp to our tree: foreach(TreeNode node in temp.Nodes) {
this.Nodes.Add(node.Clone() as TreeNode);
}
}
}
}
}
I basically just extended the TreeView class and implemented the ISerializable interface.
The tree view can be serialized by calling the Serialize function and passing it a stream to serialize to and the formatter that will handle the serialization. The formatter can be either System.Runtime.Serialization.Formatters.Binary.BinaryFormatter or System.Runtime.Serialization.Formatters.Soap.SoapFormatter (in system.runtime.serialization.formatters.soap.dll).
The deserialization is done in the same way, but make sure that if you serialized with SoapFormatter, you deserialize with SoapFormatter and same with BinaryFormatter.
One assumption about this method is: Since all nodes a serialized based on their "full name" field, no two ROOT nodes can contain the same name (Text property on the node) otherwise the serialization will fail with a SerializationException saying something about "cannot serialize the same value twice".
Awesome! Many thanks to all who contributed. I found it interesting (ok, annoying) that the latest version of the framework contained class(es) for working with XML and the ASP.NET treeview, but nothing for the windows treeview. This technique has shaved days off the current task I am working on. Again, wow! and many thanks.
Could you please post an example of how you would use this class when serializing and deserializing the TreeView I am having trouble understanding how to use the Stream parameter.
I made one adjustment to your code to eliminate the need for the assumption:
'One assumption about this method is: Since all nodes a serialized based on their "full name" field, no two ROOT nodes can contain the same name (Text property on the node) otherwise the serialization will fail with a SerializationException saying something about "cannot serialize the same value twice". '
How to serialize with TreeView?
Youngmin park
Not sure how to do this in VB, but here is the solution translated into Managed VC++. Thanks again for the great solution!
usage:
Serializing:
// remove it if it exists if (System::IO::File::Exists(path)){
System::IO::File::Delete(path);
} FileStream^ stream = gcnew FileStream(path, FileMode::CreateNew, FileAccess::Write);
// SoapFormatter^ formatter = gcnew Formatters::Soap::SoapFormatter();
BinaryFormatter^ formatter = gcnew BinaryFormatter();
serializableTreeView1->Serialize(stream, formatter);
stream->Close();
Deserializing:
FileStream^ stream = gcnew FileStream(path, FileMode::Open, FileAccess::Read);// SoapFormatter^ formatter = gcnew Formatters::Soap::SoapFormatter();
BinaryFormatter^ formatter = gcnew BinaryFormatter();
serializableTreeView1->Deserialize(stream, formatter);
stream->Close();
solution in Managed VC++
#pragma
onceusing namespace System;
using namespace System::IO;
using namespace System::Runtime::Serialization;
using namespace System::Windows::Forms;
namespace
MySerializableControls{///
<summary>/// Summary description for SerializableTreeView.
///
</summary>///
[
Serializable]public
ref class SerializableTreeView : TreeView, ISerializable{
public
: SerializableTreeView() : TreeView(){ }
public
: SerializableTreeView(SerializationInfo^ info, StreamingContext^ context) : TreeView(){
SerializationInfoEnumerator^ infoEnumerator = info->GetEnumerator();
while (infoEnumerator->MoveNext())
{
System::Windows::Forms::TreeNode^ node = (System::Windows::Forms::TreeNode^)info->GetValue
(infoEnumerator->Name, infoEnumerator->ObjectType);
if (node != nullptr)
{
Nodes->Add(node);
}
}
}
public
: void virtual GetObjectData(SerializationInfo^ info, StreamingContext context){
for each(System::Windows::Forms::TreeNode^ node in this->Nodes)
{
// info->AddValue(node->FullPath, node);
System::Guid guid = System::Guid::NewGuid();
info->AddValue(guid.ToString(),node);
}
}
/// <summary> /// Serialize all the nodes of this tree to the stream provided, using the formatter provided. /// </summary> /// <param name="stream">The stream to serialize to.</param> /// <param name="formatter">The formatter used to serialize.</param>public
: void Serialize(Stream^ stream, IFormatter^ formatter){
formatter->Serialize(stream, this);}
/// <summary> /// Recreate this tree from a serialized version. /// </summary> /// <param name="stream">the stream that contains the serialized tree.</param> /// <param name="formatter">the formatter used to desrialize the stream.</param>public
: void Deserialize(Stream^ stream, IFormatter^ formatter){
// Clear our tree:
this->Nodes->Clear();
SerializableTreeView^ temp = (SerializableTreeView^ )formatter->Deserialize(stream);
if (temp != nullptr)
{ // copy the nodes from the temp to our tree: for each(System::Windows::Forms::TreeNode^ node in temp->Nodes)
{
this->Nodes->Add((System::Windows::Forms::TreeNode^)node->Clone());
}
}
}
};
}
A. Reimann
This code has a problem, when I serialize a tree with images, after the deserialization all the ImageIndex are equal with -1, in fact the only information preserved is the Text field.
Ananth Iyer
http://www.carlosag.net/Tools/CodeTranslator/Default.aspx
http://www.kamalpatel.net/ConvertCSharp2VB.aspx
http://authors.aspalliance.com/aldotnet/examples/translate.aspx
http://www.developerfusion.co.uk/utilities/convertcsharptovb.aspx
shakeel1975
Feras11
Thanks for the code! I'm a bit of a beginner, though, and am not sure how to use this code - how does the contructor's inputs (SerializationInfo info, StreamingContext context) reference an existing TreeView Does anyone have an example of how one would take an existing TreeView and make it serializable using this class
Thanks!
Arie Ori
I want to ask do you have a version of serialize a ListView in Visual C++
Below is my effort, I use a CSV file to save all the items and a conventional way of deleting the file, create a new one after the item in ListView is deleted, reading files and display it again to listView, but it also don't work.
I was confused and don't know what to do to read and write a listView to a CSV file which is a very long and time wasting process.
I have read the code of serialize with TreeView but I also need to serialize with listView.
Here is the code I've tried:
private: System::Void listView1_KeyDown(System:
bject^ sender, System::Windows::Forms::KeyEventArgs^ e) {
elete) //delete listView di treeView juga dihapus dan sebaliknya.
how(item->Text);
how(myEnum1->Current->ToString());
ubItems sit = safe_cast<ListViewItem::ListViewSubItem^>(myEnum1->Current);
how();
String^ fileToDel="C:\\Chris\\Testing\\Assignment1\\data.txt";
String^ fileToReplace="C:\\Chris\\Testing\\Assignment1\\data.txt";
String^ backupfileToReplace="C:\\Chris\\Testing\\Assignment1\\backup.bak";
if (e->KeyCode == Keys:
{
//delete listView items before physically.
listView1->Items->RemoveAt(idxlist);
listView1->Refresh();
//backup pada waktu listView di-DEL.
//coding di file "Backup pada waktu listView di del.txt"
//update file
String^ path = "C:\\Chris\\Testing\\Assignment1\\data.txt";
// This text is added only once to the file.
// Create a file to write to.
StreamWriter^ sw = File::CreateText( path );
try
{
//save all listView items before cleared.
ListView::ListViewItemCollection^ list = this->listView1->Items;
System::Collections::IEnumerator^ myEnum = list->GetEnumerator();
int i = 0;
while ( myEnum->MoveNext() ) {
ListViewItem^ item = safe_cast<ListViewItem^>(myEnum->Current);
ListViewItem::ListViewSubItemCollection^ subitem = item->SubItems;
System::Collections::IEnumerator^ myEnum1 = subitem->GetEnumerator();
//MessageBox:
//MessageBox:
/*while ( myEnum1->MoveNext() ){
ListViewItem:
MessageBox:
}*/
//int i=0;
//while ( myEnum1->MoveNext() ){
//Writing to CSV format from listView items.
//company name from String variable "nodecomp" on Form1 which get node name selected.
//if (i==0) {
//company name
sw->Write(item->Text);
sw->Write(",");
//}
//else if (i==1) {
//employee name
sw->Write(item->Text);
sw->Write(",");
//}
//employee age
//else if (i==2) {
sw->Write(item->Text);
sw->Write(",");
//}
//gender
//else if (i==3) {
sw->Write(item->Text);
sw->Write(",");
//}
//address
//else if (i==4) {
sw->Write(item->Text);
sw->Write(",");
//}
//city
//else if (i==5) {
sw->Write(item->Text);
sw->Write(",");
//}
//zip
//else if (i==6) {
sw->Write(item->Text);
sw->Write(",");
//}
//phone
//else if (i==7) {
sw->WriteLine(item->Text);
//}
i++;
//Writing to CSV Format from listView items.
//} //while myEnum1
//count++;
File::Replace(fileToDel, fileToReplace, backupfileToReplace, false);
} //while myEnum
elete( path );
//save all listView items before cleared.
}
finally
{
if ( sw )
delete (IDisposable^)sw;
}
//update file
//delete file physically
//String^ path = "c:\\temp\\MyTest.txt";
//File:
//delete file physically
//recreate with the new listView items.
//baca file
//recreate with the new listView items.
//backup pada waktu listView di-DEL.
}
}
I look forward to hear from you soon.
Thank you very much.
big71
The problem with serializing a TreeView (or any other UI component) is that if you have to deserialize it, you have to remove the old version of your tree view and replace it with the deserialized version. Which is anoying because if you created your form with the form designer in VS 2005, then you have to syncronize all your settings with the deserialized tree. This is really anoying during design & development phase because you may make changes to your tree's properties in the designer (at design time), but forget to add those changes to your deserialized tree (at runtime).
Anyways, despite the drawbacks, I created a serializable/deserializabe tree view. The advantage with my tree view is that it doesn't destroy the tree itself, just the node structure, so you don't have to worry about setting all the properties on the treeview control itself. The disadvantage is, it has to create a temporary tree view and copy all the nodes to the current tree during deserialization.
Here is the code:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace AssetBrowserControl
{
}
I basically just extended the TreeView class and implemented the ISerializable interface.
The tree view can be serialized by calling the Serialize function and passing it a stream to serialize to and the formatter that will handle the serialization. The formatter can be either System.Runtime.Serialization.Formatters.Binary.BinaryFormatter or System.Runtime.Serialization.Formatters.Soap.SoapFormatter (in system.runtime.serialization.formatters.soap.dll).
The deserialization is done in the same way, but make sure that if you serialized with SoapFormatter, you deserialize with SoapFormatter and same with BinaryFormatter.
One assumption about this method is: Since all nodes a serialized based on their "full name" field, no two ROOT nodes can contain the same name (Text property on the node) otherwise the serialization will fail with a SerializationException saying something about "cannot serialize the same value twice".
I hope this helps..
Shawn Clark
Awesome! Many thanks to all who contributed. I found it interesting (ok, annoying) that the latest version of the framework contained class(es) for working with XML and the ASP.NET treeview, but nothing for the windows treeview. This technique has shaved days off the current task I am working on. Again, wow! and many thanks.
cjonbike
Serializing is necessary when you want to write the data structure of a class/object to a file or transmitted over a network.
Deserializing is the opposite, you have the data structure to populate a class/object from a file or network stream.
giantpanda77
It's great!
J.S.
Could you please give me a version of this code in Visual Basic
Thanks
techNick
Michael Thomas
Ray.Lamoreaux
Very nice article!
I made one adjustment to your code to eliminate the need for the assumption:
'One assumption about this method is: Since all nodes a serialized based on their "full name" field, no two ROOT nodes can contain the same name (Text property on the node) otherwise the serialization will fail with a SerializationException saying something about "cannot serialize the same value twice".
'
public
void GetObjectData(SerializationInfo info, StreamingContext context){
foreach(TreeNode node in this.Nodes){
info.AddValue(System.Guid.NewGuid().ToString(),node);
//info.AddValue(node.FullPath, node);}
}
Your code was helpful to me.
Thankyou.