Converting tree view to byte[], then back again - c#

I'm trying to convert a treeview to a byte array and then back again. So far when the form loads, it will load the structure of my documents. Then as far as I know, it will convert it to a byte array and back but I'm not sure how to convert the byte array back to the tree view.
Here is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
ListDirectory(treeView1, filepath);
}
private static void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var stack = new Stack<TreeNode>();
var rootDirectory = new DirectoryInfo(path);
var node = new TreeNode(rootDirectory.Name) { Tag = rootDirectory };
stack.Push(node);
while (stack.Count > 0)
{
var currentNode = stack.Pop();
var directoryInfo = (DirectoryInfo)currentNode.Tag;
foreach (var directory in directoryInfo.GetDirectories())
{
var childDirectoryNode = new TreeNode(directory.Name) { Tag = directory };
currentNode.Nodes.Add(childDirectoryNode);
stack.Push(childDirectoryNode);
}
foreach (var file in directoryInfo.GetFiles())
currentNode.Nodes.Add(new TreeNode(file.Name));
}
treeView.Nodes.Add(node);
}
private Byte[] SerilizeQueryFilters()
{
BinaryFormatter bf = new BinaryFormatter();
List<TreeNode> list = new List<TreeNode>();
foreach(TreeNode node in treeView1.Nodes)
{
list.Add(node);
}
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, list);
return ms.GetBuffer();
}
}
private void DeSerilizeQueryFilters(byte[] items)
{
BinaryFormatter bf = new BinaryFormatter();
try
{
using (MemoryStream ms = new MemoryStream())
{
ms.Write(items, 0, items.Length);
ms.Position = 0;
_list = bf.Deserialize(ms) as List<TreeNode>;
treeView2.Nodes.AddRange(_list.ToArray());
}
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
private void button1_Click(object sender, EventArgs e)
{
byte[] data = SerilizeQueryFilters();
DeSerilizeQueryFilters(data);
}
}
So the bit that's throwing an error at the moment is
_list = bf.Deserialize(ms) as List<TreeNode>;
and I get this error:
System.Runtime.Serialization.SerializationException
Does anyone have any ideas?

The solution was easy using the recommendation of #Fildor I stop using BinaryFormatter and now I use JSON and using the recommendation of #madreflection
I create a custom class to save the data of the TreeNode.
Custom TreeNode Class
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TreeViewStuff
{
public class Node
{
public int id;
public string text = "";
public int parentId = 0;
public bool cheked = false;
}
}
Deserialize/Serialize TreeView Class
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TreeViewStuff
{
public class TreeviewPersist
{
public static string strJson;
private static TreeView treeView_;
static public string ToJson(TreeView treeView)
{
List<Node> nodes = new List<Node>();
foreach(TreeNode node in treeView.Nodes)
{
SerializeTree(nodes, node);
}
nodes.RemoveAt(0);
return JsonConvert.SerializeObject(nodes);
}
public delegate void FunctionDelegate();
public static void FromJson(string strJson_, TreeView treeView)
{
strJson = strJson_;
treeView_ = treeView;
treeView.BeginInvoke(new FunctionDelegate(FromJson));
}
private static void FromJson()
{
treeView_.Nodes.Clear();
List<Node> nodes = JsonConvert.DeserializeObject<List<Node>>(strJson);
foreach(Node node in nodes)
{
if (node.parentId == 0)
{
TreeNode treeNode = treeView_.Nodes.Add(node.text);
treeNode.Name = $"{node.id}";
treeNode.Checked = node.cheked;
}
else
{
TreeNode[] foundNodes = treeView_.Nodes.Find($"{node.parentId}", true);
if (foundNodes.Length > 0)
{
TreeNode treeNode = foundNodes[0].Nodes.Add(node.text);
treeNode.Checked = node.cheked;
treeNode.Name = $"{node.id}";
}
}
}
}
static private void SerializeTree(List<Node> nodes, TreeNode treeNode)
{
Node node = new Node();
bool suces = Int32.TryParse(treeNode.Name, out node.id);
TreeNode parent = treeNode.Parent;
if (parent != null)
{
suces = Int32.TryParse(parent.Name, out node.parentId);
}
else
{
node.parentId = 0;
}
node.text = treeNode.Text;
node.cheked = treeNode.Checked;
nodes.Add(node);
foreach (TreeNode tn in treeNode.Nodes)
{
SerializeTree(nodes, tn);
}
}
}
}
Directories/Files to TreeView Method
private static void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
int id = 1;
var stack = new Stack<TreeNode>();
var rootDirectory = new DirectoryInfo(path);
var node = new TreeNode(rootDirectory.Name) { Tag = rootDirectory };
stack.Push(node);
while (stack.Count > 0)
{
var currentNode = stack.Pop();
var directoryInfo = (DirectoryInfo)currentNode.Tag;
foreach (var directory in directoryInfo.GetDirectories())
{
var childDirectoryNode = new TreeNode(directory.Name) { Tag = directory };
childDirectoryNode.Name = $"{id++}";
currentNode.Nodes.Add(childDirectoryNode);
stack.Push(childDirectoryNode);
}
foreach (var file in directoryInfo.GetFiles())
{
TreeNode treeNode = new TreeNode(file.Name);
treeNode.Name = $"{id++}";
currentNode.Nodes.Add(new TreeNode(file.Name));
}
}
treeView.Nodes.Add(node);
}
To make this work each TreeNode needs to have a Unique Id that is going to be saved in the name of the TreeNode as I do in the Directories/Files to TreeView Method. Thanks #Fildor and #madreflection for your help!

Related

Find CheckBox content control in word and check with Spire.Doc?

I have a word file with content control checkboxes. How to find those checkboxes with sprire.doc ???
The demo below explains how to find check box content controls and update their check states with Spire.Doc.
using System;
using System.Windows.Forms;
using Spire.Doc;
using Spire.Doc.Documents;
using System.Collections.Generic;
namespace UpdateCheckBox
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Document document = new Document();
document.LoadFromFile("CheckBoxContentControl.docx");
//Get the content controls in the document
StructureTags structureTags = GetAllTags(document);
List<StructureDocumentTagInline> tagInlines = structureTags.tagInlines;
//Loop through the controls
for (int i = 0; i < tagInlines.Count; i++)
{
//Get the control type
string type = tagInlines[i].SDTProperties.SDTType.ToString();
//Update the check state of check box
if (type == "CheckBox")
{
SdtCheckBox scb = tagInlines[i].SDTProperties.ControlProperties as SdtCheckBox;
if (scb.Checked)
{
scb.Checked = false;
}
else
{
scb.Checked = true;
}
}
}
//Save the document
document.SaveToFile("Output.docx", FileFormat.Docx);
//Open the document
WordDocViewer("Output.docx");
}
static StructureTags GetAllTags(Document document)
{
StructureTags structureTags = new StructureTags();
foreach (Section section in document.Sections)
{
foreach (DocumentObject obj in section.Body.ChildObjects)
{
if (obj.DocumentObjectType == DocumentObjectType.Paragraph)
{
foreach (DocumentObject pobj in (obj as Paragraph).ChildObjects)
{
if (pobj.DocumentObjectType == DocumentObjectType.StructureDocumentTagInline)
{
structureTags.tagInlines.Add(pobj as StructureDocumentTagInline);
}
}
}
}
}
return structureTags;
}
public class StructureTags
{
List<StructureDocumentTagInline> m_tagInlines;
public List<StructureDocumentTagInline> tagInlines
{
get
{
if (m_tagInlines == null)
m_tagInlines = new List<StructureDocumentTagInline>();
return m_tagInlines;
}
set
{
m_tagInlines = value;
}
}
}
private void WordDocViewer(string fileName)
{
try
{
System.Diagnostics.Process.Start(fileName);
}
catch { }
}
}
}

C# WPF Read/Edit CSV

I am currently writing an application in WPF C# that is some kind of helper for other processes which are written in Java. Those other processes require a configuration.csv in which different "names" are listed with a column that says "SKIP". If the column is X at Skip, my java program will skip those names and therefore their dependent processes.
If I open the CSV with Excel and edit the rows, everything works perfectly fine. That's not the problem. What I want to achieve is to list the rows into a DataGrid in a WPF App (except the first and last row), where the user can tick a checkbox to decide if he wants to skip that specific name or not. By pressing Save, the .CSV gets updated.
I already wrote some code with a friend who's more familiar with this topic. It worked fine in WinForms but doesn't work on WPF. We are not able to get the values of the checkboxes and not able to save them into the CSV.
CODE:
private void OBJ_SaveButton_Click(object sender, RoutedEventArgs e)
{
if (OBJ_DataGrid.Items.Count == 0)
{
MessageBox.Show("Kein Datensatz in der View.");
return;
}
/*if (Directory.Exists(path))
{
if (File.Exists(filepath))
{
string tmp = null;
try
{
FileStream fileStr = new FileStream(filepath, FileMode.Create);
StreamWriter strWriter = new StreamWriter(fileStr);
strWriter.WriteLine("SFObject;Skip");
for(int i=0;i< itmGrd.Count;i++)
{
switch (itmGrd[i].ItemValue)
{
case true:
tmp = itmGrd[i].ItemName + ";X";
break;
case false:
tmp = itmGrd[i].ItemName + ";";
break;
}
strWriter.WriteLine(tmp);
}
strWriter.WriteLine("SuccessMSG;");
strWriter.Close();
fileStr.Close();
LoadConf();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
MessageBox.Show("ERR_F0: Pfad nicht gefunden.");
}
else
MessageBox.Show("ERR_D0: Pfad nicht gefunden.");*/
}
private void OBJ_ReloadButton_Click(object sender, RoutedEventArgs e)
{
}
private void OBJ_DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void OBJ_DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
MessageBox.Show(e.Row.ToString());
}
void OnChecked(object sender, RoutedEventArgs e)
{
MessageBox.Show(e.Source.ToString());
}
}
public class ItemGrid
{
public ItemGrid(string name, bool rval)
{
ItemName = name;
ItemValue = rval;
}
public string ItemName { set; get; }
public bool ItemValue { set; get; }
}
public class ItemsGrid : List<ItemGrid>
{
public string path = null;
public string filepath = null;
public ItemsGrid()
{
path = String.Format(#"{0}\build\", Environment.CurrentDirectory);
filepath = Path.Combine(path + "configuration.csv");
if (Directory.Exists(path))
{
if (File.Exists(filepath))
{
string line = null;
StreamReader file = new StreamReader(filepath);
while ((line = file.ReadLine()) != null)
{
if (!line.Equals("SFObject;Skip") && !line.Equals("SuccessMSG;"))
{
string input = (line.IndexOf(";X") != -1 ? (line.Replace(";X", "")) : (line.Replace(";", "")));
Add(new ItemGrid(input, (line.IndexOf(";X") != -1 ? (true) : (false))));
}
}
file.Close();
}
else
MessageBox.Show("ERR_F0: Pfad nicht gefunden.");
}
else
MessageBox.Show("ERR_D0: Pfad nicht gefunden.");
//Add(new ItemGrid("Tom", false));
// Add(new ItemGrid("Jen", false));
}
}
This is how it looks (and should look like).
CSV:
I hope that you guys can help me out, I really don't understand why it's not working. I also have to admit that I am not any near of being proficient in C#.
I'm assuming the CSV you pasted is considered properly formatted.
// HelperClass.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfCsvSkipTicker
{
public static class HelperClass
{
public static List<ItemGrid> ReadCsv(string filepath)
{
if (!File.Exists(filepath)) return null;
var allLines = File.ReadAllLines(filepath);
var result =
from line in allLines.Skip(1).Take(allLines.Length -2)
let temparry = line.Split(';')
let isSkip =
temparry.Length > 1
&& temparry[1] != null
&& temparry[1] == "X"
select new ItemGrid { ItemName = temparry[0], ItemValue = !isSkip };
return result.ToList();
}
public static void WriteCsv(IEnumerable<ItemGrid> items, string filepath)
{
var temparray = items.Select(item => item.ItemName + ";" + (item.ItemValue ? "" : "X")).ToArray();
var contents = new string[temparray.Length + 2];
Array.Copy(temparray, 0, contents, 1, temparray.Length);
contents[0] = "SFOBject;Skip";
contents[contents.Length - 1] = "SuccessMSG;";
File.WriteAllLines(filepath, contents);
}
}
public class ItemGrid
{
public string ItemName { set; get; }
public bool ItemValue { set; get; }
}
}
And...
// MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGridView.ItemsSource = HelperClass.ReadCsv(#"PathToRead\configuration.csv");
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
var temp = new List<ItemGrid>();
for (int i = 0; i < this.dataGridView.Items.Count; i++)
{
if (this.dataGridView.Items[i] is ItemGrid) // DataGrid pads it's item collection with elements we didn't add.
temp.Add((ItemGrid)this.dataGridView.Items[i]);
}
HelperClass.WriteCsv(temp, #"PathToSave\new_configuration.csv");
}
}

Displaying only searched treenode

I have treeview in windowsform application when searching for node is performed I need to hide all the remaining node and I need to show only the searched node and its parent .like
grandParent
Parent1
child1
child2
child3.
parent2
child4
child5
if the searched node is child 3 i need to show the out put as..
grandParent
Parent1
child3
all auother are to be Hide.
Unfortunately (as far as I know) if you are using a WinForms TreeView control then hiding nodes is not as simple as setting the IsVisible property (due to the fact that the property is read only).
The only way of hiding nodes is to remove them from the Nodes collection.
This means displaying them again would require you to keep track of their location within the tree hierarchy to be able to restore them.
The following code seems to do what you require:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
using System.Xml;
using System.Diagnostics;
using System.IO;
using System.Xml.Linq;
namespace WindowsFormsApplication
{
public partial class HideRestoreNodesForm : Form
{
private List<RemovedTreeNode> _removedNodes = new List<RemovedTreeNode>();
public HideRestoreNodesForm()
{
InitializeComponent();
//AddNodesToTree();
}
private void searchButton_Click(object sender, EventArgs e)
{
TreeNode[] foundNodes = treeView1.Nodes.Find("NameOfNodeToFind", true);
if(foundNodes.Length > 0)
{
TreeNode foundNode = foundNodes[0];
HideNodes(treeView1.Nodes, foundNode);
}
}
private void HideNodes(TreeNodeCollection nodes, TreeNode visibleNode)
{
List<TreeNode> nodesToRemove = new List<TreeNode>();
foreach (TreeNode node in nodes)
{
if (!AreNodesRelated(node, visibleNode))
{
_removedNodes.Add(new RemovedTreeNode() { RemovedNode = node, ParentNode = node.Parent, RemovedNodeIndex = node.Index });
nodesToRemove.Add(node);
}
else
{
HideNodes(node.Nodes, visibleNode);
}
}
foreach (TreeNode node in nodesToRemove)
node.Remove();
}
private bool AreNodesRelated(TreeNode firstNode, TreeNode secondNode)
{
if (!IsNodeAncestor(firstNode, secondNode) && !IsNodeAncestor(secondNode, firstNode) && firstNode != secondNode)
{
return false;
}
else
{
return true;
}
}
private bool IsNodeAncestor(TreeNode nodeToCheck, TreeNode descendantNode)
{
TreeNode parentNode = descendantNode.Parent;
while (parentNode != null)
{
if (parentNode == nodeToCheck)
{
return true;
}
else
{
parentNode = parentNode.Parent;
}
}
return false;
}
private void restoreNodes_Click(object sender, EventArgs e)
{
RestoreNodes();
}
private void RestoreNodes()
{
_removedNodes.Reverse();
foreach (RemovedTreeNode removedNode in _removedNodes)
{
if (removedNode.ParentNode == null)
treeView1.Nodes.Add(removedNode.RemovedNode);
else
removedNode.ParentNode.Nodes.Insert(removedNode.RemovedNodeIndex ,removedNode.RemovedNode);
}
_removedNodes.Clear();
}
}
public class RemovedTreeNode
{
public TreeNode RemovedNode { get; set; }
public int RemovedNodeIndex { get; set; }
public TreeNode ParentNode { get; set; }
}
}
Hope this helps you.
I notice you are a new user, If this or any other questions you ask on the site provide the answers you are looking for remember to accept the answers.
See the following for more information: How does accepting an answer work?

Copy all treeView parent and children to another treeView c# WinForms

I am trying to copy the entire tree (exactly all nodes) of a treeview (completely) to another treeview using this code:
TreeNodeCollection myTreeNodeCollection = treeView1.Nodes;
TreeNode[] myTreeNodeArray = new TreeNode[treeView1.Nodes.Count];
treeView1.Nodes.CopyTo(myTreeNodeArray, 0);
treeView2.Nodes.AddRange(myTreeNodeArray);
But this does not allow me to do so, it asks to either delete the nodes in source treeview or use it Clone! How can I do that? I dont want my source treeview to lose anything in this process.
** UPDATE **
Ok guys I found a complicated code (for me!!) but how can I use this?
public static T DeepTreeCopy<T>(T obj)
{
object result = null;
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
result = (T)formatter.Deserialize(ms); ms.Close();
}
return (T)result;
}
try this
public void Copy(TreeView treeview1, TreeView treeview2)
{
TreeNode newTn;
foreach (TreeNode tn in treeview1.Nodes)
{
newTn = new TreeNode(tn.Text, tn.Value);
CopyChilds(newTn, tn);
treeview2.Nodes.Add(newTn);
}
}
public void CopyChilds(TreeNode parent, TreeNode willCopied)
{
TreeNode newTn;
foreach (TreeNode tn in willCopied.ChildNodes)
{
newTn = new TreeNode(tn.Text, tn.Value);
parent.ChildNodes.Add(newTn);
}
}
My regards
Like MohD's answer, but with recursion to get all nodes. (Nodes of childnodes)
public void CopyTreeNodes(TreeView treeview1, TreeView treeview2)
{
TreeNode newTn;
foreach (TreeNode tn in treeview1.Nodes)
{
newTn = new TreeNode(tn.Text, tn.ImageIndex, tn.SelectedImageIndex);
CopyChildren(newTn, tn);
treeview2.Nodes.Add(newTn);
}
}
public void CopyChildren(TreeNode parent, TreeNode original)
{
TreeNode newTn;
foreach (TreeNode tn in original.Nodes)
{
newTn = new TreeNode(tn.Text, tn.ImageIndex, tn.SelectedImageIndex);
parent.Nodes.Add(newTn);
CopyChildren(newTn, tn);
}
}
Using the node.Clone() function works as well...
foreach (TreeNode node in treeViewSource.Nodes)
{
treeViewTarget.Nodes.Add((TreeNode)node.Clone());
}
Adding a root node will help ensure the "PlusMinus" functionality is viewable.
TreeNode rootNode = new TreeNode("Root Node");
treeViewTarget.Nodes.Add(rootNode);
foreach (TreeNode node in treeViewSource.Nodes)
{
rootNode.Nodes.Add((TreeNode)node.Clone());
}
rootNode.Expand();
Thank you guys for the Answers. Combining all answers this worked for me. Even if the treeview has multiple levels.
public void CopyTreeNodes(TreeView treeview1, TreeView treeview2)
{
TreeNode newTn;
foreach (TreeNode tn in treeview1.Nodes)
{
newTn = new TreeNode(tn.Text, tn.Value);
CopyChildren(newTn, tn);
treeview2.Nodes.Add(newTn);
}
}
public void CopyChildren(TreeNode parent, TreeNode original)
{
TreeNode newTn;
foreach (TreeNode tn in original.ChildNodes)
{
newTn = new TreeNode(tn.Text, tn.Value);
parent.ChildNodes.Add(newTn);
CopyChildren(newTn, tn);
}
}
You can use this at the desired level
public void RootCopy(TreeView treeview1, TreeView treeview2)
{
TreeNode newNode;
foreach (TreeNode tnode in treeview1.Nodes)
{
newNode = new TreeNode(tnode.Text);
treeview2.Nodes.Add(newNode);
if (tnode.Nodes.Count != 0)
{
int _1index = tnode.Index;
ChildsCopyLevel2(_1index, treeview1, treeview2);
}
}
}
public void ChildsCopyLevel2(int index1, TreeView TV1, TreeView TV2)
{
foreach (TreeNode Tnode in TV1.Nodes[index1].Nodes)
{
string Childtext = Tnode.Text;
TV2.Nodes[index1].Nodes.Add(Childtext);
if (Tnode.Nodes.Count != 0)
{// ChildsCopyLevel3(Tnode.Nodes.Count, TV1, TV2);
int _2index = Tnode.Index;
ChildsCopyLevel3(index1, _2index, TV1, TV2);
}
}
}
public void ChildsCopyLevel3(int index1, int index2, TreeView TV1, TreeView TV2)
{
foreach (TreeNode Tnode in TV1.Nodes[index1].Nodes[index2].Nodes)
{
string Childtext = Tnode.Text;
TV2.Nodes[index1].Nodes[index2].Nodes.Add(Childtext);
}
}

event serialization

I found a working code serialization of controls, but it has not one function: there is a controls, the controls has an event, after saving it does not saves. How can I solve this problem?
Following is the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace serial
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Save control
int i = 0;
foreach (XElement element in
panel1.Controls
.OfType<Control>()
.Select(ToXml))
{
element.Save("Control" + i++ + ".xml");
}
}
private static XElement ToXml(Control control)
{
Type controlType = control.GetType();
var root = new XElement("Root",
new XAttribute("Type", controlType.AssemblyQualifiedName));
PropertyInfo[] fieldInfos = controlType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo fieldInfo in fieldInfos)
{
if (fieldInfo.CanRead && fieldInfo.CanWrite &&
fieldInfo.Name != "Font" && fieldInfo.Name != "Handle")
{
object content = fieldInfo.GetValue(control, null);
if (content != null && content.GetType().IsSerializable)
{
var serializer = new DataContractSerializer(content.GetType());
var str = new StringBuilder();
using (XmlWriter stream = XmlWriter.Create(str))
{
serializer.WriteObject(stream, content);
}
XElement data = XElement.Parse(str.ToString());
var element = new XElement("Property",
new XAttribute("Name", fieldInfo.Name),
new XAttribute("Type", fieldInfo.PropertyType.AssemblyQualifiedName)
, data);
root.Add(element);
}
}
}
return root;
}
private void button2_Click(object sender, EventArgs e)
{
panel1.Controls.Clear();
}
private void button3_Click(object sender, EventArgs e)
{
// Clear panel
panel1.Controls.Clear();
// Load control
IEnumerable<string> newControlsNames = Directory.EnumerateFiles(Environment.CurrentDirectory, "*.xml");
Control[] newControls = newControlsNames
.Select(XElement.Load)
.Select(GetControl)
.Select(c => c as Control)
.ToArray();
// Add control on panel
panel1.Controls.AddRange(newControls);
}
// get control from xml
private static object GetControl(XElement xml)
{
Type controlType = Type.GetType(xml.Attribute("Type").Value);
object control = Activator.CreateInstance(controlType);
IEnumerable<XElement> elements = xml.Elements("Property");
foreach (XElement element in elements)
{
string name = element.Attribute("Name").Value;
Type type = Type.GetType(element.Attribute("Type").Value);
XNode first = element.Nodes().First();
var serializer = new DataContractSerializer(type);
object value;
using (var stream = new MemoryStream(Encoding.Default.GetBytes(first.ToString())))
{
value = serializer.ReadObject(stream);
}
if (value != null)
{
PropertyInfo fieldInfo = controlType.GetProperty(name);
fieldInfo.SetValue(control, value, null);
}
}
return control;
}
private void button4_Click(object sender, EventArgs e)
{
MessageBox.Show("1");
}
private void button5_MouseEnter(object sender, EventArgs e)
{
MessageBox.Show("2");
}
}
}
edit:
Here's my project! http://www.fileserve.com/file/t7kUwWM
The problem with evets is, the list of delegates are not accesible from "outside" the class.
There is workaround - must use reflection and search for private fields typed as delegate (I mean custom delegate not only System.Delegate) and than serialize references to target object and target method (via System.Reflection.MethodInfo).
However this solution is very proprietary and does not guarantee the correct behaviour in all cases, because depends on private state of object.

Categories

Resources