tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルTreeViewのツリー構造固定
記事No8961
投稿日: 2009/05/15(Fri) 09:23
投稿者
はじめまして。

今のところ、TreeViewをVB2005で作成しています。

TOP
┣XXX1
┣XXX2
┗XXX3

@上記のようなツリー構造を固定(追加、削除、編集が出来ない仕様)にする。
AそのXXX1に新たなノードを追加する。
BXXX1に追加したノードをXXX2へ移動させる。
CXXX2に移動したノードをXXX3に移動させる。
DXXX3に移動したノードを削除する。
A〜Dは作成できますが、@の作成は不明です。

@のツリー構造は作成できますが、追加、削除、編集が出来ない仕様にするにはどうすればいいでしょうか?ご教授願います。

[ツリー表示へ]
タイトルRe: TreeViewのツリー構造固定
記事No8962
投稿日: 2009/05/15(Fri) 09:38
投稿者魔界の仮面弁士
> 追加、削除、編集が出来ない仕様にするにはどうすればいいでしょうか?

もちろん、貴方自身(開発者)は、追加/削除/編集できてしかるべきなのですよね?
(アプリ利用者は、追加機能/削除機能を用意してやらなければ、編集はできないはず)

とりあえず、TreeView / TreeNode / TreeNodeCollection を継承して、
それらの編集用メソッド等を Friend として用意し、元々存在している
Public なメンバのいくつかを握りつぶして、ReadOnlyCollection となるように
しむければ、外部からの操作を禁止する事はできるかも知れません。

[ツリー表示へ]
タイトルRe^2: TreeViewのツリー構造固定
記事No8971
投稿日: 2009/05/15(Fri) 16:01
投稿者
> もちろん、貴方自身(開発者)は、追加/削除/編集できてしかるべきなのですよね?

と思いましたが、作成しているうちに思いつかなかった事が沢山出てきて手落ちておりました。申し訳ありませんが、改めて加えておきます。

TOP
┣XXX1
┣XXX2
┗XXX3

@上記のようなツリー構造を固定(追加、削除、編集が出来ない仕様)にする。
AそのXXX1を指定(選択するのではなく固定プログラム)して、新たなノードを追加する。
 コンボボックスに入力し[ノード追加]ボタンクリックすると、XXX1を指定してその下層に加える。

TOP
┗XXX1
 ┗XXX1_1

Dim ZZZ As TreeNode
   If ComboBox1.Text = "" Then
      Exit Sub
   End If
ZZZ = TreeView1.SelectedNode ← どんなノードを選択するコードですが、その辺が分からないのです。 
ZZZ.Nodes.Add(New TreeNode(ComboBox1))

BXXX1に追加したXXX1_1をXXX2へ移動させると共に、新たなノードを2つ加える。
 操作は[ノード追加2]ボタンクリックするだけで移動&追加。

TOP
┣XXX1
┗XXX2
 ┣XXX1_1
 ┣XXX2_1
 ┗XXX2_2

CXXX2に移動したノードをXXX3に移動させる。
 Bと同様に、[移動]ボタンをクリックすると、下層ノード全てをXXX3へ移動。
TOP
┣XXX1
┣XXX2
┗XXX3
 ┣XXX1_1
 ┣XXX2_1
 ┗XXX2_2

こんな感じも作成していますが、つまづいてしまいました。

[ツリー表示へ]
タイトルRe^3: TreeViewのツリー構造固定
記事No8972
投稿日: 2009/05/15(Fri) 17:16
投稿者魔界の仮面弁士
> こんな感じも作成していますが、つまづいてしまいました。
どこで躓いているのでしょうか?


> ZZZ = TreeView1.SelectedNode ← どんなノードを選択するコードですが、その辺が分からないのです。
TreeView1.Nodes で、TreeView のノードの一覧(TreeNodeCollection)を得られますよね。

さらに、各ノード(TreeNode)には、親兄弟を辿るための幾つかのプロパティがあります。
 Parent    … 親(一つ上の階層にあるノード)
 Nodes     … 子供達(一つ下の階層にあるすべてのノード)
 FirstNode … 長子(一つ下の階層の先頭ノード)
 LastNode  … 末子(一つ下の階層の末尾ノード)
 PrevNode  … 兄(同一階層の一つ前のノード)
 NextNode  … 弟(同一階層の一つ後のノード)

これらを組み合わせて使う事で、任意のノードを指定できます。

[ツリー表示へ]
タイトルRe^4: TreeViewのツリー構造固定
記事No8975
投稿日: 2009/05/17(Sun) 22:56
投稿者
>どこで躓いているのでしょうか?

それはノードを”選択”して追加・削除・移動するのではなく、
特定のノードを”指定”している状態で追加するプログラムでつまづきました。
例えば、下層のノード「XXX2」を指定している状態で追加する。

[ツリー表示へ]
タイトルRe^5: TreeViewのツリー構造固定
記事No8976
投稿日: 2009/05/18(Mon) 00:41
投稿者魔界の仮面弁士
> それはノードを”選択”して追加・削除・移動するのではなく、
> 特定のノードを”指定”している状態で追加するプログラムでつまづきました。
選択は、 No8971 で光さん自身が書かれているように、SelectedNode でいけますね。
指定は、 No8972 で私が示したように、Nodes 配下のプロパティを辿って指定します。


> 例えば、下層のノード「XXX2」を指定している状態で追加する。
最初の投稿内容をみると「XXX2」と「XXX2」が混在していたのが気になりますが:

とりあえず、指定方法は幾通りもあります。たとえば、位置で指定するなら、
 N = TreeView1.Nodes(1)
ですし、ノード名(表示名ではなく、TreeNode.Nameのこと)で指定するなら、
 N = TreeView1.Nodes("XXX2")
と書けます(対象ノードが最上位階層にある場合)。

また、下位の層まで辿って探したい、あるいは同名ノードが複数ある場合には、
 Ns = TreeView1.Nodes.Find("XXX2", True)
 If Ns.Length > 0 Then
  N = Ns(0)
 End If
のように書けます。

あるいは、ノード名ではなく、表示名(Textプロパティ)から探したいのであれば、
Nodes プロパティを再帰的に列挙してやれば良いかと。

その他、Nodes.Add するノードを、Dictionary(Of String, Node) 等にて
管理しておく方法なども使えるでしょう。

# これが 2008 なら、LINQ で問い合わせる事もできたのですけれどね…。

[ツリー表示へ]
タイトルRe^6: TreeViewのツリー構造固定
記事No8977
投稿日: 2009/05/18(Mon) 08:28
投稿者
ご親切な対応、ありがとうございます。

> > 例えば、下層のノード「XXX2」を指定している状態で追加する。
> 最初の投稿内容をみると「XXX2」と「XXX2」が混在していたのが気になりますが:
同じノードですが、例をあげただけです。紛らわしい表現ですみませんでした。

>  N = TreeView1.Nodes(1)
は考えましたが、それはカウントなので、指定しづらい(処理=ループ文作成に手間かける)と考えたので避けました。

> ですし、ノード名(表示名ではなく、TreeNode.Nameのこと)で指定するなら、
>  N = TreeView1.Nodes("XXX2")

> また、下位の層まで辿って探したい、あるいは同名ノードが複数ある場合には、
>  Ns = TreeView1.Nodes.Find("XXX2", True)
もしかして、変数の事ですか?直接、変数を指定した方が、作成が早そうです。
これを使って作成してみます。
例えば、変数名が「XXX123」なら、Dim XXX123 As TreeNode = New TreeNode("XXX123")で、N = TreeView1.Nodes.Find(New TreeNode() {XXX123})ですよね?

> あるいは、ノード名ではなく、表示名(Textプロパティ)から探したいのであれば、
> Nodes プロパティを再帰的に列挙してやれば良いかと。
そうですか?Textプロパティから探す方法があるとは知りませんでした。
同じTextがあるので、使い避けたいかも?

> > # これが 2008 なら、LINQ で問い合わせる事もできたのですけれどね…。
そうですか、来年、VS2010が出るらしいですね。出るまで我慢しようかな?笑

[ツリー表示へ]
タイトルRe^7: TreeViewのツリー構造固定
記事No8978
投稿日: 2009/05/18(Mon) 13:31
投稿者魔界の仮面弁士
>>  N = TreeView1.Nodes(1)
> は考えましたが、それはカウントなので、
カウントというか、位置ですね。
そのノードの位置を同階層内の先頭に移動させた場合、TreeNode.Index は 0 になります。

┣Node1       … TreeView1.Nodes(0)
┃┣Node4     … TreeView1.Nodes(0).Nodes(0)
┃┃┣Node10  … TreeView1.Nodes(0).Nodes(0).Nodes(0)
┃┃┗Node11  … TreeView1.Nodes(0).Nodes(0).Nodes(1)
┃┗Node5     … TreeView1.Nodes(0).Nodes(1)
┃ ┣Node12  … TreeView1.Nodes(0).Nodes(1).Nodes(0)
┃ ┗Node13  … TreeView1.Nodes(0).Nodes(1).Nodes(1)
┣Node2       … TreeView1.Nodes(1).Nodes(0)
┃┣Node6     … TreeView1.Nodes(1).Nodes(0).Nodes(0)
┃┗Node7     … TreeView1.Nodes(1).Nodes(0)
┗Node3       … TreeView1.Nodes(2)
 ┣Node8     … TreeView1.Nodes(2).Nodes(0)
 ┃┣Node14  … TreeView1.Nodes(2).Nodes(0).Nodes(0)
 ┃┗Node15  … TreeView1.Nodes(2).Nodes(0).Nodes(1)
 ┗Node9     … TreeView1.Nodes(2).Nodes(1)
  ┗Node16  … TreeView1.Nodes(2).Nodes(1).Nodes(0)


> 指定しづらい
アプリが求める仕様、プログラムの実装によって、「指定しやすい」記述法は異なります。

たとえばファイルパスのように、キーとなる情報がそれぞれのノードにあるのか、
それともノードを「位置」のみで管理しているのかなど、作成したいプログラムごとの
管理方法によって適切なコードは異なりますので、先の発言では
>> 指定方法は幾通りもあります。
という発言に留めています。


>> また、下位の層まで辿って探したい、あるいは同名ノードが複数ある場合には、
>>  Ns = TreeView1.Nodes.Find("XXX2", True)
> もしかして、変数の事ですか?
変数の名前というか、ノードの名前の事です。具体的には、TreeNode.Name プロパティ。
TreeView1.Nodes.Add("Key1", "Text1") とした時の Key1 の部分という言い方もできますね。


> Dim XXX123 As TreeNode = New TreeNode("XXX123")で、N = TreeView1.Nodes.Find(New TreeNode() {XXX123})ですよね?
違います。…というか、それだと Find メソッド部はコンパイルすら通りませんよね。

第一、変数『XXX123』を保持しているなら、それをそのまま指定時に使えば良いだけで、
検索して変数『N』に入れなおす必要はないかと思いますよ。
検索しなおしたところで、変数 N と 変数 XXX123 は同じ物を指し示す事になるだけかと。

> > あるいは、ノード名ではなく、表示名(Textプロパティ)から探したいのであれば、
> > Nodes プロパティを再帰的に列挙してやれば良いかと。
> そうですか?Textプロパティから探す方法があるとは知りませんでした。
そのためのメソッドがあるわけでは無いのですが、特別な方法というわけでもありません。
単純に、各ノードを再帰的に列挙しながら、TreeNode.Text を見ていくだけですよ。

Function FindSingleNodeByText(ByVal nodes As TreeNodeCollection, ByVal text As String) As TreeNode
 For Each node As TreeNode In nodes
  If node.Text = text Then Return node
  Dim N As TreeNode = FindSingleNodeByText(node.Nodes, text)
  If N IsNot Nothing Then Return N
 Next
 Return Nothing
End Function

# 該当する複数のノードを返したい場合は、配列として返した方が良いかも。


> 同じTextがあるので、使い避けたいかも?
どのようにしてツリーを管理したいのかわからないので、明言は出来ませんが、
TreeNode.Name や TreeNode.Index や TreeNode.Text 等でも特定できないなら、
追加情報となるプロパティを、TreeNode に追加してやれば OK かと。

[ツリー表示へ]
タイトル今、仕様を少し変更しました。
記事No8980
投稿日: 2009/05/18(Mon) 21:15
投稿者
おお!!
ZZZ = TreeView1.Nodes(0).Nodes(0).Nodes(0)
という風にしたので、コンボボックスに入力して(またはリスト選択して)、ボタンをクリックしただけで、指定したノードに追加できました。

今、テストを色々してみたところ、コンボボックスへの未入力または未選択の状態でボタンをクリックすると、「未入力または未選択です。」というメッセージが表示されません。

あと、移動して追加する処理を作成中ですが、最初に追加したノードを他のノードへ移動すると、データが消えるかどうかは未確認ですが、DBに登録してあれば、ノードが移動してもついてきますよね?

@XXX1の下層に新たなノードを追加。
TOP
┗XXX1
 ┗XXX1_1
  ┗XXX1_1_1 
A @で追加した下層ノードすべてをXXX2に移動して追加。
TOP
┣XXX1
┗XXX2
 ┗XXX1_1
  ┣XXX1_1_1 
  ┣XXX1_1_2
  ┗XXX1_1_3
B
TOP
┣XXX1
┣XXX2
┗XXX3
 ┗XXX1_1
  (下層ノード全て移動)

という風に変更しましたが、この作成は少し難しくなってきました。
以上 ご教授お願いします。

[ツリー表示へ]
タイトルRe: 今、仕様を少し変更しました。
記事No8981
投稿日: 2009/05/18(Mon) 22:36
投稿者魔界の仮面弁士
> データが消えるかどうかは未確認ですが、
「データ」が何を指しているのか分かりませんが、TreeNode に関しては、
.Nodes に Add しようと、.Nodes から Remove しようと存在し続けます。
そのインスタンスを変数等に保持している限りは。

> DBに登録してあれば、ノードが移動してもついてきますよね?
ノードを別の位置に移動させる場合には、一度Remove してから、
別の場所に Add/Insert すれば OK です。DB は関係ないかと。

[ツリー表示へ]
タイトルRe^2: 今、仕様を少し変更しました。
記事No8982
投稿日: 2009/05/19(Tue) 03:15
投稿者
> > データが消えるかどうかは未確認ですが、
> 「データ」が何を指しているのか分かりませんが、

PDFやエクセルなどの事です。
でも、それぞれのデータはツリービューにノードとして追加するのではなく、グリッドビューの方で表示するつもりです。

> ノードを別の位置に移動させる場合には、一度Remove してから、
> 別の場所に Add/Insert すれば OK です。DB は関係ないかと。

それは属性&日時取得で追加したノードでなければOKかもしれません。
しかし、コンボボックスに入力したName+日時取得("hhnnss")をノード名「入力_日時取得」として追加したり、DBに登録している属性をノード名として追加したりする手もあるので、その辺は不明です。だから、ノード名をキープしながら移動したいので、DBは関係あると思いますが、関係ないでしょうか?特に日時取得は毎回ランダムに変わるため、移動する時は大変ですよ?いちいちソースを書き換えなければならないし。だから、その事を踏まえた作成を考えているのです。

[ツリー表示へ]
タイトルRe^3: 今、仕様を少し変更しました。
記事No8984
投稿日: 2009/05/19(Tue) 10:00
投稿者魔界の仮面弁士
>>> データが消えるかどうかは未確認ですが、
>> 「データ」が何を指しているのか分かりませんが、
> PDFやエクセルなどの事です。
> でも、それぞれのデータはツリービューにノードとして追加するのではなく、グリッドビューの方で表示するつもりです。
今は、TreeView の話をしているのですよね。
発言内容からでは、TreeView と PDF/Excel との関係が見えてきません。

今までの一連の投稿の中に、PDFファイルやExcelファイルを参照しているという話は
一度も出ていませんので、唐突に「データ」とだけ言われても、話に付いていけません。

もし、それらファイルの話が今後の質問の上で重要な部分であるのであれば、
情報を小出しにすることはせず、その仕様を明らかにしてください。

逆に、ファイルの話と TreeView の質問との間に関連性が薄いのであれば、
話の流れをややこしくしてしまうだけなので、その話は横に置いておいてください。


>> ノードを別の位置に移動させる場合には、一度Remove してから、
>> 別の場所に Add/Insert すれば OK です。DB は関係ないかと。
> それは属性&日時取得で追加したノードでなければOKかもしれません。
属性…ですか。それは、ファイルの 読取専用/アーカイブ/非可視/システム/圧縮属性の事ですか?
「OK『かも』しれない」、という表現も気になりますが…。

何にせよ、そのノードに記載される情報がどこから得た物であるにしろ、
ノードは常に移動可能であり、「ノードの位置を変更する」という作業とは無関係かと。
(これは、アプリの仕様として移動させたくない、という話とは別の意味です)


> しかし、コンボボックスに入力したName+日時取得("hhnnss")をノード名「入力_日時取得」として追加したり、DBに登録している属性をノード名として追加したりする手もあるので、その辺は不明です。
コンボボックスというのは、No8971 に出てきていた
>>>> そのXXX1を指定(選択するのではなく固定プログラム)して、新たなノードを追加する。
>>>> コンボボックスに入力し[ノード追加]ボタンクリックすると、XXX1を指定してその下層に加える。
の事なのですよね。何度か読み返してみたのですが、アプリの仕様をまだ読み取れません。


読み合わせると、XXX1 のノード名が「入力_日時取得」であるという表現であるように
見えましたが、まず、この部分の意味が不明瞭であると感じました。

光さんが現在作成している画面、および、その仕様を知らない第三者にも分かるよう、
話の筋道を立てて、もう少し噛み砕いて説明して頂けないでしょうか。

なお、今までに挙げられた情報から、私は下記のように認識しています。

・『ノード名』というからには、(TreeNode.Text の事ではなく)TreeNode.Name の事を
 指しているものであると連想すれば良いのかな?
・そして XXX1 がそのノード名だと思っていたのだけれども、No8977 の発言内容に
 照らし合わせると、どうもこれはノードを表す変数名を指しているらしい。
・ノード名は、「入力_日時取得」という表現になっているらしい。ただしこれが、
 「"入力_日時取得" という固定文字列」を表しているのか、それとも
 「日付を元に生成される文字列」なのかといった点は読み取れない。

そして、そこから紡ぎ出したのが下記ですが…意図の見えないコードになってしまいました。

Private XXX1 As TreeNode
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Dim nodeName As String = "入力_日時取得"    'この部分が不明瞭
    Dim nodeText As String = "XXX1"             '画面に表示されるテキスト?
    XXX1 = TreeView1.Nodes.Add(nodeName, nodeText)
End Sub

なお、その前の発言にあった
>>>> そのXXX1を指定(選択するのではなく固定プログラム)して、新たなノードを追加する。
>>>> コンボボックスに入力し[ノード追加]ボタンクリックすると、XXX1を指定してその下層に加える。
の部分は、下記のコードを連想しています。

Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    If ComboBox1.Text.Length = 0 Then
        MessageBox.Show("コンボボックスに入力されていません。")
        Return
    End If
    Dim parentNode As TreeNode = TreeView1.SelectedNode
    Dim nodes As TreeNodeCollection
    If parentNode Is Nothing Then
        nodes = TreeView1.Nodes
    Else
        nodes = parentNode.Nodes
    End If
    nodes.Add(ComboBox1.Text).EnsureVisible()   'nodes.Insert の方が良い?
End Sub


> だから、ノード名をキープしながら移動したいので、DBは関係あると思いますが、
ノード名をキープしながら移動、という部分が良く分かりませんが、
たとえば No.8978 の図で言えば、Node11 の位置を Node10 の前に持っていきたいなら
 Node10 = TreeView1.Nodes(0).Nodes(0).Nodes(0)
 Node11 = TreeView1.Nodes(0).Nodes(0).Nodes(1)
という状態において、
 Node11.Remove()
 Node10.Parent.Nodes.Insert(Node10.Index, Node11)
と記述する事ができます。位置は変わっても、変数名/ノード名/表示名は変化しません。


> 特に日時取得は毎回ランダムに変わるため、
日時取得、というのがどういう作業を指しているのか説明されていないようですが、
たとえば、ファイルの更新日を取得する場合や、PC のシステム日付を取得する場合、
その値はランダムではあるとは言えません。ランダムであるという事は、
法則性が無いという意味になってしまいますが、本当にそうなのですか?


> 移動する時は大変ですよ?いちいちソースを書き換えなければならないし。
> だから、その事を踏まえた作成を考えているのです。
DB があれば、ソースを書き換えずに済むと考えておられる事はわかりましたが、
その根拠が全く示されていないように見えたので、判断に困っているところです。

[ツリー表示へ]
タイトルもう一度整理して冷静に考えてみました。
記事No8985
投稿日: 2009/05/19(Tue) 17:44
投稿者
まず、ツリービューのノードの追加、削除、移動、および移動時の追加&削除などを理解する事が目的でした。だから、最初の記事のように書いた訳ですが、DBを使った場合、作成しているうちに段々矛盾を感じました。それで、仕様を変更したり、話が変わったりしてしまいました。また、ランダム(自由、でたらめに)という言葉を使うこと自体は悪かったと思います。申し訳ありませんでした。

特に、XXX1、XXX2、XXX3の下層に複数のノードを追加すると、その下層のノードを選択して移動させる必要がある事を頭に入れていませんでした。
魔界の仮面弁士さんが書いたソースを参考に作成してみます。

[ツリー表示へ]
タイトルRe: もう一度整理して冷静に考えてみました。
記事No8986
投稿日: 2009/05/20(Wed) 10:28
投稿者魔界の仮面弁士
あれ、分かりやすい詳細な追加解説が書かれていたと思っていたのですが、
今日見たら、説明文が削除されていますね。
# 日付指定の Format の仕方に問題があったので、指摘しようと思っていたのですが。


> 特に、XXX1、XXX2、XXX3の下層に複数のノードを追加すると、その下層のノードを選択して移動させる必要がある事を頭に入れていませんでした。
ノードを移動させると、その子孫階層のノードも一緒に移動する事になりますから、
子孫ノードを一緒に移動させたいかどうかが肝になりますね。

たとえば、No.8978 の

┣Node1
┃┣Node4
┃┃┣Node10
┃┃┗Node11
┃:
┃┗Node5
┃ ┣Node12
┃ ┗Node13
┣Node2
┃┣Node6
┃┗Node7
┗Node3★
 ┣Node8
 ┃┣Node14
 ┃┗Node15
 ┗Node9
  ┗Node16

に対して下記の 4 行を実行すると、★のノード(Node3) がNode1 配下の : の場所に移動します。

 Dim Node3 As TreeNode = TreeView1.Nodes(2)
 Dim Node1Children As TreeNodeCollection = TreeView1.Nodes(0).Nodes
 Node3.Remove()
 Node1Children.Insert(1, Node3)

この結果は、下図の☆のようになります。
Node3 配下のノードもまとめて移動していますね。

┣Node1
┃┣Node4
┃┃┣Node10
┃┃┗Node11
┃┣Node3☆
┃┃├Node8
┃┃│├Node14
┃┃│└Node15
┃┃└Node9
┃┃ └Node16
┃┗Node5
┃ ┣Node12
┃ ┗Node13
┗Node2
 ┣Node6
 ┗Node7

[ツリー表示へ]
タイトルRe^2: もう一度整理して冷静に考えてみました。
記事No8987
投稿日: 2009/05/21(Thu) 18:56
投稿者
> あれ、分かりやすい詳細な追加解説が書かれていたと思っていたのですが、
> 今日見たら、説明文が削除されていますね。
削除したのではなく、修正です。ここは削除の機能が見当たらないので。

> # 日付指定の Format の仕方に問題があったので、指摘しようと思っていたのですが。
もしかして、指摘しようとしたのは月のmと秒のnのことでしょうか?
それはすでに解決済みです。

>この結果は、下図の☆のようになります。
>Node3 配下のノードもまとめて移動していますね。
うーん、というか、私は下層の複数ノードから選択して、他のノードへ移動したいのです。

Node0
┣Node1
┃┣Node3
┃┃┣Node7★1
┃┃┃┗任意1
┃┃┣Node8
┃┃┃┗任意1
┃┃┗Node9
┃┃ ┗任意1
┃┗Node4
┃ ┣Node10
┃ ┃┗任意1
┃ ┣Node11★2
┃ ┃┗任意1
┃ ┗Node12
┗Node2
 ┣Node7 ☆1(移動した)
 ┃┣任意1
 ┃┣任意2_1(新たな追加)
 ┃┗任意2_2(新たな追加)
 ┗Node11 ☆2(移動した)
  ┣任意1
  ┣任意2_1(新たな追加)
  ┗任意2_2(新たな追加)

という感じで作成したいです。

[ツリー表示へ]
タイトルRe^3: もう一度整理して冷静に考えてみました。
記事No8988
投稿日: 2009/05/21(Thu) 19:46
投稿者魔界の仮面弁士
> > あれ、分かりやすい詳細な追加解説が書かれていたと思っていたのですが、
> > 今日見たら、説明文が削除されていますね。
> 削除したのではなく、修正です。ここは削除の機能が見当たらないので。
あ、いえ。投稿そのものが削除されたという話ではなく、修正機能を用いて
No.8985 内の説明文を削除したのかな、という意味です。すみません、紛らわしい書き方でしたね。

> > # 日付指定の Format の仕方に問題があったので、指摘しようと思っていたのですが。
> もしかして、指摘しようとしたのは月のmと秒のnのことでしょうか?
実行すると n がそのまま出てしまうので、それは自己解決されると思っていました。
(あと、秒は s ですよね。それに、m/n ではなく m/n だった気が)

> それはすでに解決済みです。
「年」に関する指摘をしようかと思っていました。あの記述だと、OS の設定が
和暦モードになっていると、2009 ではなく 21 になってしまうでしょうから。
まぁ、本題とは無関係なのですけれど。

> うーん、というか、私は下層の複数ノードから選択して、他のノードへ移動したいのです。

★1/★2 を削除し、☆1/☆2 の位置に割り当て直すために、

(1) Node7 と Node11 をそれぞれ Remove し、TreeView に割り当てられていない状態に戻す。
(2) 未割り当て状態となった Node7/Node11 の Nodes に、任意2_1/任意2_2 を Add する。
(3) 3 人の子持ちとなった Node7 と Node 11 を、Node2 の Nodes に Add する。

という手順を踏めば、移動させられるかと思います。


Dim srcNodes As New List(Of TreeNode)()
srcNodes.Add(TreeView1.Nodes(0).Nodes(0).Nodes(0).Nodes(0)) 'Node7
srcNodes.Add(TreeView1.Nodes(0).Nodes(0).Nodes(1).Nodes(1)) 'Node11

Dim destNode As TreeNode = TreeView1.Nodes(0).Nodes(1) 'Node2
For Each t As TreeNode In srcNodes
    t.Remove()
    t.Nodes.Add("任意2_1")  '新たな追加
    t.Nodes.Add("任意2_2")  '新たな追加
    destNode.Nodes.Add(t)
Next

[ツリー表示へ]
タイトルRe^4: もう一度整理して冷静に考えてみました。
記事No9000
投稿日: 2009/05/23(Sat) 04:09
投稿者
> No.8985 内の説明文を削除したのかな、という意味です。すみません、紛らわしい書き方でしたね。
了解です。

> (あと、秒は s ですよね。それに、m/n ではなく m/n だった気が)
あ、s=秒 n=分でしたね。苦笑

> 「年」に関する指摘をしようかと思っていました。あの記述だと、OS の設定が
> 和暦モードになっていると、2009 ではなく 21 になってしまうでしょうから。
> まぁ、本題とは無関係なのですけれど。
でも、こちらのほうではyyyyにしても、正常に表示されています。
先ほど、ヘルプ(VS2005環境)で再確認したところ、Format関数を使う場合は月=M、分=m のようです。同じMとmなので紛らわしいけどね。

> Dim srcNodes As New List(Of TreeNode)()
> srcNodes.Add(TreeView1.Nodes(0).Nodes(0).Nodes(0).Nodes(0)) 'Node7
> srcNodes.Add(TreeView1.Nodes(0).Nodes(0).Nodes(1).Nodes(1)) 'Node11

あ、また説明が悪かったと思います。
私が言いたかったのは、複数ノードからひとつのノード(下層ノードも含む)を選択して移動するようにしたい。これをひとつずつ繰り返したい。

If Not TreeView1.Nodes.IsReadOnly Then
 If (TreeView1.SelectedNode IsNot Nothing) Then
  Dim t As TreeNode = TreeView1.SelectedNode
  TreeView1.Nodes.Remove(t)
  TreeView1.Nodes(0).Nodes(1).Nodes.Insert(TreeView1.Nodes.Count, t)
 End If
End If

これはいいなとは思いましたが、

>    t.Nodes.Add("任意2_1")  '新たな追加
>    t.Nodes.Add("任意2_2")  '新たな追加

を加えるにはまた違う内容になるため、色々作成してみましたが反映されてません。

[ツリー表示へ]
タイトルRe^5: もう一度整理して冷静に考えてみました。
記事No9007
投稿日: 2009/05/24(Sun) 22:42
投稿者魔界の仮面弁士
> > 「年」に関する指摘をしようかと思っていました。あの記述だと、OS の設定が
> > 和暦モードになっていると、2009 ではなく 21 になってしまうでしょうから。
> でも、こちらのほうではyyyyにしても、正常に表示されています。
OS の設定(コントロールパネルの地域設定)が、西暦モードに設定されている場合、
先のコードにある yyyy は 2009 を返します。一方、和暦モードに設定されていた場合は、
(2009 ではなく) 21 が返されます。その点は把握しておられますでしょうか。

地域設定に連動して表示形式を切り替えたいのか、それとも、環境に依存することなく、
常に同じ形式で表示させたいのかは、アプリケーションの求める仕様によって異なりますが、
もしも、「20090523」や「2009/05/23」のように桁数を固定的に出力したいのだとしたら、
西暦/和暦が切り替わってしまっては都合が悪いでしょうから、常に西暦で出力するための
コードを紹介しようかと思っていました。元のコードが削除されたので、投稿は取りやめましたが。


> 先ほど、ヘルプ(VS2005環境)で再確認したところ、Format関数を使う場合は
> 月=M、分=m のようです。同じMとmなので紛らわしいけどね。
あれ?? No.8987 にて「それはすでに解決済みです」とあったので、もっと前に
その情報を得ていたのかと思っていましたが…別の方法で解決されていたのですね。


> 私が言いたかったのは、複数ノードからひとつのノード(下層ノードも含む)を選択して移動するようにしたい。これをひとつずつ繰り返したい。
No.8987 に提示いただいた図の意味を、
 ・複数ノード(Node0〜Node4、Node7〜Node11)からなる階層がある。
 ・そこから、ひとつのノード Node7★1(およびその子孫ノード)を選択して、
  それを Node7 ☆1の位置に移動させ、さらにそこに 2 つのノードを追加する。
 ・さらに、別のノード Node11★2(およびその子孫ノード)を選択して、
  それを Node11 ☆2の位置に移動させ、さらにそこに 2 つのノードを追加する。
という意味に捉えたのですが、そういう意味では無かったのでしょうか。

なお「選択」という言葉から、SelectedNode を使うのかな、とも思ったのですが、以前、
>>> ZZZ = TreeView1.SelectedNode ← どんなノードを選択するコードですが、その辺が分からないのです。 
とあったので、SelectedNode を使わずに指定する方法を記述しました。
(もっとも、今回の主眼点は移動法にあるので、ノードの指定法は本題ではありませんけれども)


> If Not TreeView1.Nodes.IsReadOnly Then
>  If (TreeView1.SelectedNode IsNot Nothing) Then
>   Dim t As TreeNode = TreeView1.SelectedNode
>   TreeView1.Nodes.Remove(t)
>   TreeView1.Nodes(0).Nodes(1).Nodes.Insert(TreeView1.Nodes.Count, t)
>  End If
> End If
> これはいいなとは思いましたが、
そのコードは、ヘルプなどに挙げられているサンプルに手を加えたもののようですね。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.treenodecollection.isreadonly.aspx
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.treenodecollection.remove.aspx
http://msdn.microsoft.com/ja-jp/library/5w99w164.aspx



> >    t.Nodes.Add("任意2_1")  '新たな追加
> >    t.Nodes.Add("任意2_2")  '新たな追加
> を加えるにはまた違う内容になるため、色々作成してみましたが反映されてません。
まだ完成はしていないものの、作成の見通しは立ってきたといったところでしょうか。
頑張ってください。何か不明な点があればお手伝いしますよ。

[ツリー表示へ]
タイトルRe^6: もう一度整理して冷静に考えてみました。
記事No9010
投稿日: 2009/05/25(Mon) 01:43
投稿者
> OS の設定(コントロールパネルの地域設定)が、西暦モードに設定されている場合、
> 先のコードにある yyyy は 2009 を返します。一方、和暦モードに設定されていた場合は、
> (2009 ではなく) 21 が返されます。その点は把握しておられますでしょうか。
すみません。私の勘違いです。把握していませんでした。
実際、和暦に変更して実行してみたところ、確かに、2009→21になってましたね。
なので、↓

> あれ?? No.8987 にて「それはすでに解決済みです」とあったので、もっと前に
> その情報を得ていたのかと思っていましたが…別の方法で解決されていたのですね。
は解決していません。私の勘違いでした。
解決するにはもしかして、if文を使って、和暦なら変換。西暦ならそのまま続行という形ですか?

If 和暦取得
 和暦→西暦変換
Else
 西暦コードをそのまま続行
End If

> > 私が言いたかったのは、複数ノードからひとつのノード(下層ノードも含む)を選択して移動するようにしたい。これをひとつずつ繰り返したい。
> No.8987 に提示いただいた図の意味を、
>  ・複数ノード(Node0〜Node4、Node7〜Node11)からなる階層がある。
>  ・そこから、ひとつのノード Node7★1を選択して、
>   それを Node7 ☆1の位置に移動させ、さらにそこに 2 つのノードを追加する。
>  ・さらに、別のノード Node11★2(およびその子孫ノード)を選択して、
>   それを Node11 ☆2の位置に移動させ、さらにそこに 2 つのノードを追加する。
> という意味に捉えたのですが、そういう意味では無かったのでしょうか。
はい、その通りです。最初は指定して移動と言いましたが、ノードを新規登録する時、複数になっていくので、そこからノードを1つずつ移動する事になるとは頭に入れていませんでした。

> なお「選択」という言葉から、SelectedNode を使うのかな、とも思ったのですが、以前、
> >>> ZZZ = TreeView1.SelectedNode ← どんなノードを選択するコードですが、その辺が分からないのです。 
> とあったので、SelectedNode を使わずに指定する方法を記述しました。
結局、元に戻りました。

> > If Not TreeView1.Nodes.IsReadOnly Then
> >  If (TreeView1.SelectedNode IsNot Nothing) Then
> >   Dim t As TreeNode = TreeView1.SelectedNode
> >   TreeView1.Nodes.Remove(t)
> >   TreeView1.Nodes(0).Nodes(1).Nodes.Insert(TreeView1.Nodes.Count, t)
> >  End If
> > End If
> > これはいいなとは思いましたが、
> そのコードは、ヘルプなどに挙げられているサンプルに手を加えたもののようですね。
はい、そうです。

> まだ完成はしていないものの、作成の見通しは立ってきたといったところでしょうか。
> 頑張ってください。何か不明な点があればお手伝いしますよ。
今のところ、悪戦苦闘ですが、頑張ります。いろいろありがとうございました。
(和暦→西暦変換については調べておきます。)

[ツリー表示へ]
タイトルRe^7: もう一度整理して冷静に考えてみました。
記事No9012
投稿日: 2009/05/25(Mon) 11:05
投稿者魔界の仮面弁士
> 解決するにはもしかして、if文を使って、和暦なら変換。西暦ならそのまま続行という形ですか?
分岐は不要です。常に西暦で変換する方法としては、

(案1) Format 関数の代わりに、String.Format(IFormatProvider, String, データ) の
 メソッドを使い、第1引数に西暦対応カルチャ(例えば、InvariantCulture)を指定する。

(案2) 現在のスレッドの CurrentCulture プロパティを、西暦対応カルチャに差し替える。

などがあります。System.Globalization 名前空間について調べてみてください。


ちなみに、hh と HH も別物ですね。>Format書式

その他、日付なら区切記号、数値なら小数点記号や3桁区切記号など、地域設定に
依存する書式は意外と多いので、和暦設定に変更したり、日付区切りを「/」から「-」に
変更しただけで動かなくなってしまう事の無いように注意が必要です。

[ツリー表示へ]
タイトルツリービューに関しては解決できました。
記事No9049
投稿日: 2009/06/02(Tue) 23:25
投稿者
>Dim srcNodes As New List(Of TreeNode)()
>srcNodes.Add(TreeView1.Nodes(0).Nodes(0).Nodes(0).Nodes(0)) 'Node7

srcNodes.Add(TreeView1.SelectedNode) に書き換えましたら、解決できました。

和暦→西暦に変換する処理はいまだに悪戦苦闘中ですが、ツリービューと関係ないため、「解決」とさせていただきます。解決出来たら、「解決!」と入れる必要があるという記事を見落としていましたので、返事が遅れてしまい、申し訳ありませんでした。

魔界の仮面弁士さん、色々ありがとうございました。

[ツリー表示へ]