博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

.net 序列化和反序列化自定义treenode类

Posted on 2008-12-23 08:25  james.dong  阅读(1280)  评论(3编辑  收藏  举报

要存储一个类型,序列化是最简单的一种实现方式,TreeView本省并不支持序列化,但是TreeNode支持,因此需要从TreeNode下手, 所有序列化TreeView其实就是序列化TreeNode.

1. 自定义一个类SerialzeTreeNode继承TreeNode继承并实现ISerializable接口,其实TreeNode已经实现了ISerializable接口,在实现这个接口时要调用基类TreeNode的Serialize函数,要不然序列化的节点会不全,在Serialize函数中添加自己的序列化逻辑, 

2. 重写所有的TreeNode构造函数,特别是与序列化有关的那个构造函数,public TreeNode(SerializationInfo serinfo, StreamingContext context)就是这个了,要不然就不能正确的反序列化了 
3. 有可能的话实现一个IDeserializationCallback接口,以便于在反序列化后初始化一些变量之类的动作,因为,反序列化只调用反序列化的那个构造函数. 
4. 添加泛型支持,其实也可以用Tag用来存储要序列化的值,但是Tag是object的,不是很好,因此增加一个泛型 
变量是很有意义的,这样便于强化类型也能够很好的利用IDE的智能感知功能. 
public class SerializTreeNode<T>:TreeNode,ISerializable 

  public T TTag; 

5. 如果要使用小图标的话还要做些工作,虽然查看反序列化中的数据,有ImageSelectedIndex项,但是却无效,因此在实现ISerializable接口中顺便把ImageSelectedIndex属性也序列化进去,然后在反序列化的时候设置其值,这样就可以保存其图片索引了.Key与Index冲突,只能一个有效,因此可以二选一,看TreeView是如何设置图片的了. 
6. 对自定义类加上Serializable可序列化标记,要不然都正确了还是无法正确工作的.,同时泛型的那个类也必须要标记为Serializable,否则也会出错. 
7. 扩展TreeView提供序列化和反序列化的函数以保存树节点和加载保存的树节点. 
  public interface ISerializeTreeView 
  { 
  bool SaveTreeView(string filename); 
  bool LoadTreeView(string filename); 
  } 
可以定义这样的一个接口  

 

二:拷贝对象到剪切板

Add object to Clipboard using C# in a couple of ways 

This is a simple example of using the ClipBoard to transport objects. In this example I will generate a TreeNode and save it to a ClipBoard entry. I will then retrieve this node, cast it and either add it to the root of the TreeView or add it to the selected node's child nodes.

Method 1

Step 1: Copy new TreeNode to Clipboard
  private void button1_Click(object sender, EventArgs e)
  {
  TreeNode t = new TreeNode("ClipBoardNode");
  Clipboard.SetData("TreeNode", t);
  }
 

Step 2: Paste new TreeNode from Clipboard to TreeView
 
  private void button2_Click(object sender, EventArgs e)
  {
  TreeNode t = (TreeNode)Clipboard.GetData("TreeNode");
  if (treeView1.SelectedNode == null)
  treeView1.Nodes.Add(t);
  else
  treeView1.SelectedNode.Nodes.Add(t);
  }

 

Method 2

Another way to append to the Clipboard is the method SetDataObject and GetDataObject. There is however some difference here.
You do not provide a key, you simply save it to a designated location
You are limited to the objects which you cast the returned object back into as you can see from the image below.

To solve this I made two simple helper methods which would serialize the object to a binary representation and then get the base64String of that data, thus giving me a string object. I then put this into the ClipBoard and going the other way I did the opposite. Converted the base64String into a byte array, instantiated a MemoryStream with it and then deserialized the data returning an object. It is then up to the calling code to cast the object.
The helper methods

 
  private string Serialize(object objectToSerialize)
  {
  string serialString = null;
  using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
  {
  BinaryFormatter b = new BinaryFormatter();
  b.Serialize(ms1, objectToSerialize);
  byte[] arrayByte = ms1.ToArray();
  serialString = Convert.ToBase64String(arrayByte);
  }
  return serialString;
  }
  private object DeSerialize(string serializationString)
  {
  object deserialObject = null;
  byte[] arrayByte = Convert.FromBase64String(serializationString);
  using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream(arrayByte))
  {
  BinaryFormatter b = new BinaryFormatter();
  deserialObject = b.Deserialize(ms1);
  }
  return deserialObject;
  }
Method Code 2 Steps

Step 1: Copy new TreeNode to Clipboard
  private void button1_Click_1(object sender, EventArgs e)
  {
  TreeNode t = new TreeNode("ClipBoardNode");
  Clipboard.SetData("TreeNode", Serialize(t));
  }
 

Step 2: Paste new TreeNode from Clipboard to TreeView
  private void button2_Click(object sender, EventArgs e)
  {
  TreeNode t = (TreeNode)DeSerialize(Clipboard.GetData("TreeNode").ToString());
  if (treeView1.SelectedNode == null)
  treeView1.Nodes.Add(t);
  else
  treeView1.SelectedNode.Nodes.Add(t);
  }