C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.59243 の関連記事表示

<< 0 >>
■59243  Re[3]: TreeViewを動的に操作
□投稿者/ よねKEN -(2011/05/19(Thu) 21:57:46)
    C#のバージョンなどの開発環境が明示されていないので、参考になるかわかりませんが、
    LINQ(C#3.0 .NET Framework3.5以上で使用可)を使って実装してみました。
    
    LINQを使うのが初めてなので、効率的にかけているかまではわかりませんので、全面的な信頼はなさらないよう。
    (たとえばデータ量が多くなった場合にどうなのか?とか、もっとシンプルになるはずとか)
    
    ◆コードの前提:
      treeView1とbutton1を配置していて、button1をクリックしたらツリービューが作成されます。
    ◆実装内容の補足:
      処理をしやすいように、まず以下のようなデータの変換を行ってから、ツリービューを構成しています。
    
    [商品テーブル]
    商品   商品   使用
    コード 名     商品
    "111", "AAA", "222"
    "111", "AAA", "444"
    "111", "AAA", "555"
    "222", "BBB", "333"
    "333", "CCC", ""
    "444", "DDD", "333"
    "444", "DDD", "666"
    "555", "EEE", ""
    "666", "FFF", ""
    
             ↓
    
    [子商品テーブル] … 子の商品から見た表
    商品   商品   親商品
    コード 名     コード
    "111", "AAA", ""
    "222", "BBB", "111"
    "333", "CCC", "222"
    "333", "CCC", "444"
    "444", "DDD", "111"
    "555", "EEE", "111"
    "666", "FFF", "444"
    
    
    '-- コードはここから --
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Windows.Forms;
    using System.Linq;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private DataTable dt;
            private void Form1_Load(object sender, EventArgs e)
            {
                dt = new DataTable("商品テーブル");
                dt.Columns.Add("商品コード", typeof(string));
                dt.Columns.Add("商品名", typeof(string));
                dt.Columns.Add("使用商品", typeof(string));
    
                dt.Rows.Add("111", "AAA", "222");
                dt.Rows.Add("111", "AAA", "444");
                dt.Rows.Add("111", "AAA", "555");
                dt.Rows.Add("222", "BBB", "333");
                dt.Rows.Add("333", "CCC", "");
                dt.Rows.Add("444", "DDD", "333");
                dt.Rows.Add("444", "DDD", "666");
                dt.Rows.Add("555", "EEE", "");
                dt.Rows.Add("666", "FFF", "");
            }
    
            private class 商品
            {
                public string 商品コード { get; private set; }
                public string 商品名 { get; private set;}
                public string 使用商品 { get; private set;}
    
                public 商品(string 商品コード, string 商品名, string 使用商品)
                {
                    this.商品コード = 商品コード;
                    this.商品名 = 商品名;
                    this.使用商品 = 使用商品;
                }
    
                public override bool Equals(object obj)
                {
                    商品 s = obj as 商品;
                    if (s == null) return false;
                    return this.商品コード.Equals(s.商品コード);
                }
    
                public override int GetHashCode()
                {
                    return this.商品コード.GetHashCode();
                }
    
                public override string ToString()
                {
                    return string.Format("{0},{1},{2}", this.商品コード, this.商品名, this.使用商品);
                }
            }
    
            private class 子商品
            {
                public string 商品コード { get; private set; }
                public string 商品名 { get; private set; }
                public string 親商品コード { get; private set; }
    
                public 子商品(string 商品コード, string 商品名, string 親商品コード)
                {
                    this.商品コード = 商品コード;
                    this.商品名 = 商品名;
                    this.親商品コード = 親商品コード;
                }
    
                public override bool Equals(object obj)
                {
                    子商品 s = obj as 子商品;
                    if (s == null) return false;
                    return this.商品コード.Equals(s.商品コード) && this.親商品コード.Equals(s.親商品コード);
                }
    
                public override int GetHashCode()
                {
                    return this.商品コード.GetHashCode() * 10 + this.親商品コード.GetHashCode();
                }
    
                public override string ToString()
                {
                    return string.Format("{0},{1},{2}", this.商品コード, this.商品名, this.親商品コード);
                }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                var 商品テーブル =
                    from DataRow row in dt.Rows
                    select new 商品(row.Field<string>("商品コード"), row.Field<string>("商品名"), row.Field<string>("使用商品"));
    
                // 商品テーブルを子の商品からまとめなおしたテーブル。子からその親の商品コードを引くことができる。
                var 子商品テーブル =
                    (from 親商品 in 商品テーブル
                     join 子商品 in 商品テーブル on 親商品.商品コード equals 子商品.使用商品 into 商品s
                     from 商品 in 商品s.DefaultIfEmpty()
                     select new 子商品(親商品.商品コード, 親商品.商品名, (商品 == null ? "" : 商品.商品コード))).Distinct();
    
                int count = 子商品テーブル.Count(); // 最終的なノードの数になる
    
                // 一回の「foreach (子商品 商品 in 処理対象商品)」で処理済みとなった親商品コードの一覧
                // クエリ:処理対象商品の抽出に利用
                List<string> processed = new List<string>() { "" };
    
                // 一回の「foreach (子商品 商品 in 処理対象商品)」の処理中の親商品コードの一覧
                List<string> processing = new List<string>();
    
                // TreeNode.NodesもTreeView.Nodesも一律扱えるように
                // 商品コードとその子を管理するTreeNodeCollectionのペアを保管しておく
                Dictionary<string, TreeNodeCollection> allNodes = new Dictionary<string, TreeNodeCollection>();
                allNodes.Add("", treeView1.Nodes);
    
                while (allNodes.Count < count)
                {
                    // 前回処理した商品コードを親に持つ子の商品のみを処理対象とする
                    // ツリーの上位階層の商品コードから順に処理していくため
                    var 処理対象商品 =
                        from 商品 in 子商品テーブル
                        join 処理済商品コード in processed on 商品.親商品コード equals 処理済商品コード
                        select 商品;
    
                    processing.Clear();
                    foreach (子商品 商品 in 処理対象商品)
                    {
                        TreeNode node = new TreeNode(商品.商品コード + ":" + 商品.商品名);
                        allNodes[商品.親商品コード].Add(node);
    
                        if (!allNodes.ContainsKey(商品.商品コード))
                        {
                            allNodes.Add(商品.商品コード, node.Nodes);
                        }
                        processing.Add(商品.商品コード);
                    }
                    processed = new List<string>(processing);
                }
    
                treeView1.TopNode.Expand();
    
            }
    
        }
    }
    
記事No.59207 のレス /過去ログ99より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -