none
TreeView操作に関して RRS feed

  • 質問


  • TreeView操作に関して相談させて頂きたいと思います。

    現状、簡単なツリーの操作(追加、削除、移動)を行っているのですが
    Undo処理の対応が必要になり、undo管理クラスを生成しました。
    これはコマンドパターンで実装されており、
    ICommanのexecute部分を各命令が実装するつもりです。

    例:ノード追加コマンドはexecute処理の中でTreeViewへTreeNodeを追加する。etc


    そして、undo処理が行われると、
    一度、ツリーノードを初期化し(スナップショットを取った時点に戻す)
    全コマンドを古いものから実行します。

    そこで問題なのですが
    ノード追加コマンド内で
    『~のノードに新規にノードを追加』のような処理をしたいのですが
    TreeVireをクリアしてしまうので
    『~のノードに・・・』の『~の』部分である『追加対象ノード(TreeNode)』が不明になります。

    なので、『ノード追加コマンド』では『追加対象ノードのFullPath』を記憶して置き、
    コマンド実行時には『追加対象ノードのFullPath』からTreeNodeを検索し、
    TreeNodeに対して、ノードの追加を実行したいのですが
    『FullPath』からTreeNodeを取得する方法は御座いますでしょうか?

    2009年9月25日 16:34

回答

  • まだまだ学習中で実践経験がないので答えない方がいいのかもしれませんが…。

    FullPath から TreeNode を知るのは無理そうです(可能かもしれませんが)。
    FullPath を記憶する代わりに操作対象の親ノード名を記録しておき、
    ツリーノードの Find メソッドで目的の TreeNode を取得するというかんじになるように思います。



    あ、ごめんなさい。
    目的の TreeNode に対する処理を行うとき、
    当然その親ノードは既に追加されているはずなので、
    親ノードへの参照とその FullPath はわかりますよね。

    なので、各 TreeNode の FullPath と そのオブジェクトへの参照を対応づけて記録し、
    FullPath で検索をかけて目的の TreeNode を知りたい
    ということだったんでしょうか。
    • 回答としてマーク zilch_1975 2009年9月26日 12:09
    2009年9月26日 3:29
  • ぜんぜん別のアプローチで、

    static InstanceDescriptor[] save( TreeView tree ){
      var converter = TypeDescriptor.GetConverter( typeof( TreeNode ) );
      return tree.Nodes.OfType<TreeNode>().Select( n => (InstanceDescriptor)converter.ConvertTo( n, typeof( InstanceDescriptor ) ) ).ToArray();
    }

    static void undo( TreeView tree, InstanceDescriptor[] descriptors ){
      tree.Nodes.Clear();
      foreach( var descriptor in descriptors )
        tree.Nodes.Add( (TreeNode)descriptor.Invoke() );
    }

    何をやっているかというと、TreeNodeの状態をInstanceDescriptorという形で記憶します。
    もう少し説明すると、
    Visual StudioのフォームデザイナでTreeViewのノードを編集するとその内容がソースコードに反映されると思います。
    それは内部的にはTreeNodeをInstanceDescriptorに変換し、InstanceDescriptorをCodeDom(ソースコード)に変換しています。
    この機能を利用し、中間状態で保持しておくことでundoに利用できるのではと思います。
    • 回答としてマーク zilch_1975 2009年9月26日 12:09
    2009年9月26日 3:46

すべての返信

  • まだまだ学習中で実践経験がないので答えない方がいいのかもしれませんが…。

    FullPath から TreeNode を知るのは無理そうです(可能かもしれませんが)。
    FullPath を記憶する代わりに操作対象の親ノード名を記録しておき、
    ツリーノードの Find メソッドで目的の TreeNode を取得するというかんじになるように思います。



    あ、ごめんなさい。
    目的の TreeNode に対する処理を行うとき、
    当然その親ノードは既に追加されているはずなので、
    親ノードへの参照とその FullPath はわかりますよね。

    なので、各 TreeNode の FullPath と そのオブジェクトへの参照を対応づけて記録し、
    FullPath で検索をかけて目的の TreeNode を知りたい
    ということだったんでしょうか。
    • 回答としてマーク zilch_1975 2009年9月26日 12:09
    2009年9月26日 3:29
  • ぜんぜん別のアプローチで、

    static InstanceDescriptor[] save( TreeView tree ){
      var converter = TypeDescriptor.GetConverter( typeof( TreeNode ) );
      return tree.Nodes.OfType<TreeNode>().Select( n => (InstanceDescriptor)converter.ConvertTo( n, typeof( InstanceDescriptor ) ) ).ToArray();
    }

    static void undo( TreeView tree, InstanceDescriptor[] descriptors ){
      tree.Nodes.Clear();
      foreach( var descriptor in descriptors )
        tree.Nodes.Add( (TreeNode)descriptor.Invoke() );
    }

    何をやっているかというと、TreeNodeの状態をInstanceDescriptorという形で記憶します。
    もう少し説明すると、
    Visual StudioのフォームデザイナでTreeViewのノードを編集するとその内容がソースコードに反映されると思います。
    それは内部的にはTreeNodeをInstanceDescriptorに変換し、InstanceDescriptorをCodeDom(ソースコード)に変換しています。
    この機能を利用し、中間状態で保持しておくことでundoに利用できるのではと思います。
    • 回答としてマーク zilch_1975 2009年9月26日 12:09
    2009年9月26日 3:46
  • SweetSmileさん

    ご返答有難う御座いました。

    再帰処理でFullPathを比較すれば、
    FullPathから期待したTreeNodeが取得出来ました。

    生産性優先の為に速度面を犠牲にして簡単なundo処理を実装したので
    undoの度にTreeViewの全ノードをクリアしてコマンド処理を実行しますが
    命令コマンドがTreeNodeのオブジェクトを保持出来る処理系に変更しようと思います。

    有難う御座いました。
    2009年9月26日 12:09
  • 佐祐理さん

    少々、ハイレベルなので少し勉強してから
    佐祐理さんの実装を考慮したいと思います。

    有難う御座いました。

    2009年9月26日 12:10