Contents
ファイルに保存する
ツリービューのアイテムをファイルに保存してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { private void buttonSave_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); var dr = dialog.ShowDialog(); if (dr != DialogResult.OK) return; List<TreeNodeEx> treeNodeExs = syncTreeView1.GetTreeNodeExs(null); var xml = new System.Xml.Serialization.XmlSerializer(typeof(List<TreeNodeEx>)); var sw = new System.IO.StreamWriter(dialog.FileName); xml.Serialize(sw, treeNodeExs); sw.Close(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class SyncTreeView : UserControl { public List<TreeNodeEx> GetTreeNodeExs(TreeNodeEx startNode) { if (startNode == null) return treeViewEx1.GetTreeNodeExs(null); else { TreeNode[] nodes = treeViewEx1.Nodes.Find(startNode.Key, true); if (nodes.Length == 1) return treeViewEx1.GetTreeNodeExs(nodes[0]); else return null; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
internal class TreeViewEx : TreeView { public List<TreeNodeEx> GetTreeNodeExs(TreeNode startNode) { List<TreeNodeEx> ret = new List<TreeNodeEx>(); List<TreeNode> nodes = GetTreeNodes(startNode); int startLevel = 0; if (startNode != null) startLevel = startNode.Level; foreach (TreeNode node in nodes) { TreeNodeEx ex = new TreeNodeEx(); ex.Text = node.Text; ex.Level = node.Level - startLevel; ex.Key = node.Name; ex.ToolTipText = node.ToolTipText; ex.BackColorArgb = node.BackColor.ToArgb(); ex.Checked = node.Checked; ex.ForeColorArgb = node.ForeColor.ToArgb(); ex.ImageIndex = node.ImageIndex; ex.IsExpanded = node.IsExpanded; ex.SelectedImageIndex = node.SelectedImageIndex; ex.Data = node.Tag; ret.Add(ex); } return ret; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
internal class TreeViewEx : TreeView { public List<TreeNode> GetTreeNodes(TreeNode startNode) { List<TreeNode> ret = new List<TreeNode>(); TreeView view = this; if (view.Nodes.Count == 0) return ret; TreeNode curNode = null; TreeNode endNode = null; if (startNode == null) { curNode = view.Nodes[0]; endNode = null; } else { curNode = startNode; endNode = startNode; } ret.Add(curNode); if (startNode != null && startNode.FirstNode == null) return ret; bool b = true; while (true) { if (b && curNode.FirstNode != null) { curNode = curNode.FirstNode; ret.Add(curNode); } else if (curNode.NextNode != null) { curNode = curNode.NextNode; ret.Add(curNode); b = true; } else { curNode = curNode.Parent; b = false; if (curNode == endNode) break; } } return ret; } } |
SyncTreeView内にGetTreeNodeExsというメソッドを作成しています。これはツリービュー内のTreeNodeをリストに格納して、シリアル化するために必要なTreeNodeのデータをTreeNodeExオブジェクトにコピーをしています。
TreeNodeExクラスはこんな感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class TreeNodeEx { public string Text { set; get; } public string ToolTipText { set; get; } public string Key { set; get; } public int Level { set; get; } public int BackColorArgb { set; get; } public int ForeColorArgb { set; get; } public bool Checked { set; get; } public int ImageIndex { set; get; } public int SelectedImageIndex { set; get; } public bool IsExpanded { set; get; } public object Data { set; get; } } |
ファイルから読み出す
ファイルとして保存できたら読み出しもできるようにしたいものです。ファイルから読み出すためには
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { private void buttonLoad_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); var dr = dialog.ShowDialog(); if (dr != DialogResult.OK) return; XmlSerializer serializer = new XmlSerializer(typeof(List<TreeNodeEx>)); StreamReader sr = new StreamReader(dialog.FileName); List<TreeNodeEx> nodeExs = (List<TreeNodeEx>)serializer.Deserialize(sr); sr.Close(); syncTreeView1.RestoreNodes(treeNodeExs, null, InsertTo.LastChild); } } |
これで読み出すことができます。読み出したデータをつかってツリービューのアイテムを再構築する必要がありますが、これをやっているのがRestoreNodesメソッドです。
ノードをつくるためには親ノードが必要です。そのためノードをつくったらその階層の最後のアイテムがなにかわかるように配列内に保存しています。これをつかってツリーアイテムを再構築しています。ひとつできあがったらそのコピーをつくって他のツリービューにもアイテムを挿入しています。またノードの開閉状態も再現しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class SyncTreeView : UserControl { public void RestoreNodes(List<TreeNodeEx> nodeExs, TreeNodeEx targetNode, InsertTo insertTo) { List<TreeNode> newNodes = treeViewEx1.RestoreNodes(nodeExs); if (targetNode == null) { foreach (TreeViewEx view in SyncGroup.TreeViews) { view.RestoreTreeView(newNodes, null, insertTo); } } else { if (targetNode._group != null && targetNode._group.TreeViews.Count > 0) { TreeNode[] nodes = targetNode._group.TreeViews[0].Nodes.Find(targetNode.Key, true); if (nodes.Length == 1) { foreach (TreeViewEx view in SyncGroup.TreeViews) { TreeNode[] targets = view.Nodes.Find(targetNode.Key, true); if(targets.Length == 1) view.RestoreTreeView(newNodes, targets[0], insertTo); } } } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
internal class TreeViewEx : TreeView { public List<TreeNode> RestoreNodes(List<TreeNodeEx> nodeExs) { if (nodeExs.Count == 0) return null; TreeView view1 = new TreeView(); view1.BeginUpdate(); TreeNode[] vs = new TreeNode[nodeExs.Max(x => x.Level) + 1]; DateTime dt = DateTime.Now; string key0 = dt.Ticks.ToString(); int i = 0; foreach (TreeNodeEx ex in nodeExs) { i++; TreeNode node = new TreeNode(); node.Text = ex.Text; node.ToolTipText = ex.ToolTipText; node.Name = key0 + "-" + i.ToString(); if (ex.ForeColorArgb == 0) node.ForeColor = Color.Empty; else node.ForeColor = Color.FromArgb(ex.ForeColorArgb); if (ex.BackColorArgb == 0) node.BackColor = Color.Empty; else node.BackColor = Color.FromArgb(ex.BackColorArgb); node.Checked = ex.Checked; node.ImageIndex = ex.ImageIndex; node.SelectedImageIndex = ex.SelectedImageIndex; node.Tag = ex.Data; if (ex.Level == 0) { view1.Nodes.Add(node); vs[0] = node; } else { vs[ex.Level - 1].Nodes.Add(node); vs[ex.Level] = node; } } List<TreeNode> treeNodes = new List<TreeNode>(); foreach (var node in view1.Nodes) treeNodes.Add((TreeNode)node); view1.Nodes.Clear(); view1.Dispose(); return treeNodes; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
internal class TreeViewEx : TreeView { public void RestoreTreeView(List<TreeNode> newNodes, TreeNode targetNode, InsertTo insertTo) { BeginUpdate(); if (targetNode == null) Nodes.Clear(); for (int i = 0; i < newNodes.Count; i++) { TreeNode node = newNodes[i]; if (targetNode == null) { if (insertTo == InsertTo.LastChild) Nodes.Add((TreeNode)node.Clone()); if (insertTo == InsertTo.FirstChild) Nodes.Insert(i, (TreeNode)node.Clone()); } else { TreeNode[] nodes = Nodes.Find(targetNode.Name, true); if (nodes.Length == 1) { if (insertTo == InsertTo.LastChild) nodes[0].Nodes.Add((TreeNode)node.Clone()); else if (insertTo == InsertTo.FirstChild) nodes[0].Nodes.Insert(i, (TreeNode)node.Clone()); else if (insertTo == InsertTo.NextNode) { int index = nodes[0].Index; if (nodes[0].Parent != null) nodes[0].Parent.Nodes.Insert(index + 1 + i, (TreeNode)node.Clone()); else Nodes.Insert(index + 1 + i, (TreeNode)node.Clone()); } else if (insertTo == InsertTo.PrevNode) { int index = nodes[0].Index; if (nodes[0].Parent != null) nodes[0].Parent.Nodes.Insert(index + i, (TreeNode)node.Clone()); else Nodes.Insert(index + i, (TreeNode)node.Clone()); } } } } EndUpdate(); } } |
アイテムの色、背景色はColor型からint型に変換して保存していますが、そのままではBackColorはColor.Emptyになっています。そのままBackColor.ToArgb()を実行すると0が返され、これをそのまま利用するとノードの背景色が黒になってしまいます。そこでファイルを読み取ったときにBackColorArgbが0のときはColor.FromArgbは使わずColor.Emptyを設定しています。