ゲームエフェクトデザイナーのブログ (新)

レポート記事とかUE4のマテリアルとか。C#とかも触ったり。

C# XMLへの階層構造の保存メモ3(TreeView編)

前回に続き、今度は実践編ということで元々やりたかったことを再帰処理で行ってみます。

フォームはこんな感じ。
あらかじめTreeViewに適当に孫以上の深い階層を追加しておきます。

f:id:moko_03_25:20190610235639j:plain

実装はこんな感じ。
using System.Xml.Linq;」を先頭に追加するのをお忘れなく。。

private void Form1_Load(object sender, EventArgs e)
{
	// ツリーを全て展開
	treeView1.ExpandAll();
}

private void Button1_Click(object sender, EventArgs e)
{
	XmlSave();
}

private void XmlSave()
{
	// XMLの内容の定義
	var xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

	// 構造ごとの要素を定義
	XElement Sample = new XElement("サンプル");
	xml.Add(Sample);

	// TreeViewのノード情報をnodesコレクションに格納
	TreeNodeCollection nodes = treeView1.Nodes;
	// ループ
	foreach (TreeNode node in nodes)
	{
		// 自分自身のノードを定義  
		XElement n = new XElement("ルートノード");
		xml.Root.Add(n);

		// 再帰処理用
		XmlRecursive(node, n);
	}

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

// 再帰処理用
private void XmlRecursive(TreeNode node, XElement n)
{
	XElement name = new XElement("Name", node.Text);
	n.Add(name);

	// ループ
	foreach (TreeNode tn in node.Nodes)
	{
		// 自分自身のノードを定義  
		XElement n2 = new XElement("子ノード");
		n.Add(n2);

		// 自分自身を呼び出す
		XmlRecursive(tn, n2);
	}
}

結果はこんな感じ。

f:id:moko_03_25:20190610235658g:plain

ノードのラベル名は<Name>タグに格納しています。
同じように、ノードに紐づけたクラスインスタンスの情報‥例えばノードと紐づけたTextBoxの内容など色々な情報をタグにして埋め込むことができます。

これが不要で単純にノードのラベル名がそのままタグ名になるだけで良いなら、こんなまわりくどくする必要は無くて、もっと簡略化できると思います。

ちなみに文字列をXMLに書き出す際、改行が失われてしまいます。
なので改行を表す特殊文字に置き換えて読み書きすることで対応しました。
「memo.Text.Replace("\r\n", "[:NL:]");」みたいな感じです。
タブスペースは何もしなくても保持されました。

置換の方法はこちらをどうぞ。

XMLの書き出しは初めて試した状態なので、もっと良い方法があればぜひコメントくださいっ。