質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

3366閲覧

TreeView ノードの階層表示について

NapoleonClaf2

総合スコア0

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/10/15 09:26

編集2020/10/16 02:23

実現したいこと

ASP.NET Web Formsで以下を実装したいです。

・DBから取得したデータを画面上のTreeViewに表示
・取得したデータは3種類で「親-子-孫」の関係性で表示する。

なお現状はこの要件を満たしたTreeViewを表示できているのですが、
foreach文を多用しておりスマートではない。(現在のソース)
BindingInfo.DataSourceを使用することによって記述量が減ることは調べたことによりわかっているが、
「親-子」までの関係性までしか表示させることができなかった。(BindingInfo.DataSource等を使用したソース)

サンプルコードでは記述量が多く見えないが、実際の開発となると非常に可読性が悪くなっている状態であるため
foreach文をできるだけ減らし、コードの可読性を向上させたいです。

繰り返し処理の簡略化等々の
何かよい解決方法がありましたら、どなたかご教授願います。

※実装イメージ
![イメージ説明

環境

  • .NET Core 3.1 SDK
  • VisualStudio 2019 Professional
    • EntityFrameworkVisualEditor
  • ComponentOne Enterprise 2020V2

現在のソースコード(サンプル)

C#

1 //すべて同一クラス内で作成しているものだと思ってください。 2 //親ノードクラス 3 private class Parent 4 { 5 public long Id { get; set; } 6 public string Name { get; set; } 7 8 //コンストラクタ 9 public Parent(long Id, string Name) 10 { 11 this.Id = Id; 12 this.Name = Name; 13 } 14 } 15 //子ノードクラス 16 private class Child 17 { 18 public long Id { get; set; } 19 public string Name { get; set; } 20 public long Parent_Id { get; set; } 21 22 //コンストラクタ 23 public Child(long Id, string Name, long Parent_Id) 24 { 25 this.Id = Id; 26 this.Name = Name; 27 this.Parent_Id = Parent_Id; 28 } 29 } 30 //孫ノードクラス 31 private class Grands 32 { 33 public long Id { get; set; } 34 public string Name { get; set; } 35 36 public long Child_Id { get; set; } 37 38 //コンストラクタ 39 public Grands(long Id, string Name, long Child_Id) 40 { 41 this.Id = Id; 42 this.Name = Name; 43 this.Child_Id = Child_Id; 44 } 45 } 46 47 //---------ツリービュー作成------------------ 48 private void CreateTreeView() 49 { 50 //DBから取得してきた各情報------------------- 51 List<Parent> parents = new List<Parent>(); 52 List<Child> children = new List<Child>(); 53 List<Grands> grands = new List<Grands>(); 54 55 parents.Add(new Parent(1, "AAA")); 56 parents.Add(new Parent(2, "BBB")); 57 parents.Add(new Parent(3, "CCC")); 58 59 children.Add(new Child(1, "AAA_A", 1)); 60 children.Add(new Child(2, "BBB_A", 2)); 61 children.Add(new Child(3, "CCC_A", 3)); 62 children.Add(new Child(4, "AAA_B", 1)); 63 children.Add(new Child(5, "BBB_B", 2)); 64 children.Add(new Child(6, "CCC_B", 3)); 65 66 grands.Add(new Grands(1, "AAA_A_A", 1)); 67 grands.Add(new Grands(2, "BBB_A_A", 2)); 68 grands.Add(new Grands(3, "CCC_A_A", 3)); 69 grands.Add(new Grands(4, "AAA_A_B", 1)); 70 grands.Add(new Grands(5, "BBB_A_B", 2)); 71 grands.Add(new Grands(6, "CCC_A_B", 3)); 72 grands.Add(new Grands(7, "AAA_B_A", 4)); 73 grands.Add(new Grands(8, "BBB_B_A", 5)); 74 grands.Add(new Grands(9, "CCC_B_A", 6)); 75 //DBから取得してきた各情報 end ------------------- 76 77 foreach (Parent parent in parents) 78 { 79 //親ノードのインスタンス、親ノードに値を設定 80 C1TreeNode parentNode = new C1TreeNode(); 81 parentNode.SetValue(parent.Name); 82 83 //子ノードの設定 84 foreach (Child child in children.Where(x => x.Parent_Id == parent.Id)) 85 { 86 //子ノードのインスタンス、子ノードの値を設定 87 C1TreeNode childNode = new C1TreeNode(); 88 childNode.SetValue(child.Name); 89 90 //孫ノードの設定 91 foreach (Grands grand in grands.Where(x => x.Child_Id == child.Id)) 92 { 93 94 //孫ノードのインスタンス、孫ノードの値を設定 95 C1TreeNode grandNode = new C1TreeNode(); 96 grandNode.SetValue(grand.Name); 97 98 //子ノードに孫ノードを設定 99 childNode.Nodes.Add(grandNode); 100 } 101 //親ノードに子ノードを設定 102 parentNode.Nodes.Add(childNode); 103 } 104 //ツリービューに親ノードを設定 105 c1TreeView.Nodes.Add(parentNode); 106 }

(BindingInfo.DataSource等を使用したソース)

private class NodeData { public Parent parentNodeData { get; set; } //親ノード public List<Child> childNodeData { get; set; } //子ノードリスト //コンストラクタ public NodeData(Parent parentNodeData, List<Child> childNodeData) { this.parentNodeData = parentNodeData; this.childNodeData = childNodeData; } } //---------ツリービュー作成------------------ private void CreateTreeView() { //DBから取得してきた各情報-------------------  //同上のため省略 //DBから取得してきた各情報 end ------------------- //ノード設定用ノードリスト List<NodeData> nodeData = new List<NodeData>(); foreach(Parent parent in parents) { //親ノードと紐づいている子ノードのリストを取得し、ノードリストを設定する List<Child> child1 = children.Where(x => x.Parent_Id == parent.Id).ToList(); nodeData.Add(new NodeData(parent, child1)); } //データソースの設定 this.associationTreeView.BindingInfo.DataSource = nodeData; // データメンバ(子ノードリスト)の設定 this.associationTreeView.BindingInfo.DataMember = "\childNodeData"; // ノート表示名に利用するメンバを設定 c1TreeView.Columns[0].DisplayFieldName = "parentNodeData\Nam

ボールドテキスト

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2020/10/16 10:06 編集

何を目標にしているかよくわかりませんが、SelectMany を使えばネストは減ります。また各ノードに同じインターフェースを持たせれば親・子・孫をある程度シームレスに扱えるでしょうし、探索部分のみ別クラスに追い出すという手もあります。あるいは再帰を使って深さ優先探索するのも手だと思いますし、Interactive Extensions の Expand メソッドで幅優先探索をする手もあります。foreach を減らしたいということですが、このコードを見る限りではループ回数自体は減ると思えません。親・子・孫の間の共通部分を抽象化してフラットに扱えば多重ループが一重ループあるいは再帰に落とし込めると思います。
NapoleonClaf2

2020/10/19 02:47

Zuishin様 ご回答ありがとうございます。 foreachを減らしたいというのが最終的な目標でした。 が、ループ回数が減るとは思いませんとのことですので、 現状はこのソースを維持してみようと思います。 再帰などはじめて聞く単語が出てきましたのでそちらの方も一度調べてみて 今のソースに実装できるなら実装する…といった形にしたいと思います。 的確なアドバイスありがとうございました。
guest

回答1

0

自己解決

皆様ご閲覧ありがとうございました。
Zuishin様のアドバイスの元
再帰等を使用してスマートなソースを作成できるように頑張ってみます。

投稿2020/10/20 00:40

編集2020/10/22 08:32
NapoleonClaf2

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問