まず、保存するためのテーブルを設計します。
【SQLite】
CREATE TABLE "TREEVIEW" ( "ROWNAME" TEXT, "hasChild" INTEGER NOT NULL DEFAULT 0, "parentName" TEXT NOT NULL, "index" INTEGER NOT NULL, PRIMARY KEY("ROWNAME") );
using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace learning { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //https://dobon.net/vb/dotnet/control/tvdraganddrop.html //TreeView1へのドラッグを受け入れる treeView1.AllowDrop = true; //イベントハンドラを追加する treeView1.ItemDrag += new ItemDragEventHandler(TreeView1_ItemDrag); treeView1.DragOver += new DragEventHandler(TreeView1_DragOver); treeView1.DragDrop += new DragEventHandler(TreeView1_DragDrop); } private void button2_Click(object sender, EventArgs e) { treeView1.Nodes.Clear(); var connectionString = "Data Source=learning.db"; using (var cn = new SQLiteConnection(connectionString)) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { using (var context = new DataContext(cn)) { Dictionary<int, TreeNode> Dtree = new Dictionary<int, TreeNode>(); TREEVIEW[] clone = context.GetTable<TREEVIEW>().ToArray().Clone() as TREEVIEW[]; foreach (var q in context.GetTable<TREEVIEW>().ToArray().OrderBy(y => y.index)) { Dtree.Add(q.index, new TreeNode(q.ROWNAME)); } foreach (var q in context.GetTable<TREEVIEW>().ToArray().OrderByDescending(y => y.index)) { var name = q.ROWNAME; var pare = q.parentName; if (pare != "ROOT") { var gg = clone.Single(x => x.ROWNAME == pare); Dtree[gg.index].Nodes.Insert(0,Dtree[q.index].Clone() as TreeNode); Dtree.Remove(q.index); } } foreach(var q in context.GetTable<TREEVIEW>().ToArray().Where(y => y.parentName == "ROOT").OrderBy(z => z.index)) { treeView1.Nodes.Add(Dtree[q.index]); } } } } treeView1.ExpandAll(); } private void button1_Click(object sender, EventArgs e) { treeToDb(treeView1.Nodes); } private void treeToDb(TreeNodeCollection tnc) { var connectionString = "Data Source=learning.db"; int c = 0; using (var cn = new SQLiteConnection(connectionString)) { cn.Open(); using (var cmd = new SQLiteCommand(cn)) { using (var context = new DataContext(cn)) { context.ExecuteCommand("DELETE FROM TREEVIEW"); var views = context.GetTable<TREEVIEW>(); recursiveTree(views, context, tnc, ref c); } } } } private void recursiveTree(Table<TREEVIEW> table, DataContext dc, TreeNodeCollection treeNodeCollection, ref int C) { foreach (TreeNode tnn in treeNodeCollection) { var Rowname = tnn.Text; var hAschild = tnn.GetNodeCount(true) > 0 ? 1 : 0; var lEvel = tnn.Level; var parent = tnn.Parent is null ? "ROOT" : tnn.Parent.Text; var kind = tnn.ImageIndex; table.InsertOnSubmit(new TREEVIEW(Rowname, hAschild, parent,C)); dc.SubmitChanges(); C++; if (hAschild == 1) { recursiveTree(table, dc, tnn.Nodes, ref C); } } } } [Table(Name = "TREEVIEW")] public class TREEVIEW { [Column(Name = "ROWNAME", CanBeNull = false, DbType = "NVARCHAR", IsPrimaryKey = true)] public string ROWNAME { get; set; } [Column(Name = "hasChild", CanBeNull = false, DbType = "int", IsPrimaryKey = false)] public int hasChild { get; set; } [Column(Name = "parentName", CanBeNull = false, DbType = "NVARCHAR", IsPrimaryKey = false)] public string parentName { get; set; } [Column(Name = "index", CanBeNull = false, DbType = "int", IsPrimaryKey = false)] public int index { get; set; } public TREEVIEW() { } public TREEVIEW(string rowname, int HasChild, string ParentName,int Index) { ROWNAME = rowname; hasChild = HasChild; parentName = ParentName; index = Index; } } }
より、ドラッグ&ドロップでNodeを移動できるようにしておくと便利です。(上記コード内にはメソッド名のみ記載しています。)