Javaを少しやってオブジェクト指向がわかりはじめた位の初心者です。
今回はMicrosoft Visual Studio Express 2013 for Windows Desktopを使用して
Windows 7 のエクスプローラーの再現をC#で試みています。
そこでTreeNodeの操作の仕方が良く分からず、早くから詰まってしまいました。
以下、再現出来なかったことをできるようにするためには、ソースのどの部分を直せばいいのでしょうか?
■今のところ再現したいこと
Windows7のフォルダツリーとアドレスバーの動作(と、選択フォルダ配下画像の表示)
■再現出来たこと
フォルダツリー表示(TreeNode)
アドレスバーの表示(FlowLayoutPanelにフォルダ名が表示されるButtonをAdd)
フォルダツリーのみでディレクトリ変更(上の階層に行く)、アドレスバー更新
画像の表示
■再現出来なかったこと(今回解決したいこと)
フォルダツリーでディレクトリ変えた後アドレスバーでディレクトリ変更(上の階層に行く)
→System.IndexOutOfRangeException発生
その前には以下のことをしています。Findしても検索結果がゼロになってしまいます。
◯押されたButtonのTextプロパティを取得
(アドレスバーにButtonを追加する時、Textプロパティにフルパスを入れておいた)
◯取得したフルパスをキーにフォルダツリーからNodeを検索
→ここで検索結果ゼロ
◯検索されたNodeをSelectedNodeに追加しようとするも、配列に何もないため例外発生
→TreeNodeのSelectedNodeプロパティにTreenodeを代入してもnullのまま
「folderTree.SelectedNode」で現在TreeNodeで選択されているNodeを取得し
上にさかのぼったりする処理をしたいのですが、
「folderTree.Nodes.Clear();」で「folderTree.SelectedNode」がnullになることに気づき、
以下処理を試してみましたが、folderTree.SelectedNodeは更新されずnullのままでした。
TreeNode tmp = folderTree.SelectedNode; //現在のSelectedNodeを一時保管 folderTree.Nodes.Clear(); //TreeNodeを初期化→folderTree.SelectedNodeがnull updateFolderTree(currentSelectedNode); //TreeNode追加 folderTree.SelectedNode = tmp; //一時保管していたNodeを再格納
■エラーが起きる具体例
①起動時のフォルダツリーの状態
- C:\
- D:\
②フォルダツリーで「C:\」「ProgramFiles」と選択
③アドレスバーは「[C:] [Program Files] [ProgramFiles配下のフォルダ]」と表示され
フォルダツリーが以下の状態になる
- C:\
- Program Files
- ProgramFiles配下のフォルダ
- C:\配下の他フォルダ
- D:\
④アドレスバーの[C:] [Program Files] [TortoiseSVN]のいずれかを押す
→UpdateTreeViewイベントが発生
→System.IndexOutOfRangeExceptionが発生して処理中断
■ソース
※プロパティの名前
folderTree…フォルダツリー
addressBar…アドレスバー
picturePanel…サムネイル表示画面
processBar…プロセスバー
lang
1public partial class Form1 : Form 2{ 3 private String currentDirectoryPath; 4 private TreeNode folderTreeNode; 5 6 public Form1() 7 { 8 InitializeComponent(); 9 initialFolderTree(); 10 } 11 12 #region Event 13 private void folderTree_BeforeExpand(object sender, TreeViewCancelEventArgs e) 14 { 15 updateFolderTree(e.Node); 16 } 17 18 private void folderTree_AfterSelect(object sender, TreeViewEventArgs e) 19 { 20 updateFolderTree(e.Node); 21 } 22 private void update_formSize(object sender, EventArgs e) 23 { 24 Size size = Form1.ActiveForm.Size; 25 split_middle.Size = new Size(size.Width, size.Height - 80); 26 } 27 28 private void picturePanel_enterMouse(object sender, EventArgs e) 29 { 30 picturePanel.Focus(); 31 } 32 private void folderTree_enterMouse(object sender, EventArgs e) 33 { 34 folderTree.Focus(); 35 } 36 /* 37 * ツリービューの更新(アドレスバーのButtonを押下した際に発生) 38 */ 39 private void folderTree_Update(Object sender, EventArgs e) 40 { 41 TreeNode currentSelectedNode = null; 42 //アドレスバーを連続で操作するとSelectedNodeがnullになりNullReferenceExceptionが発生 43 if (folderTree.SelectedNode != null) 44 { 45 currentSelectedNode = folderTree.SelectedNode; 46 } 47 else 48 { 49 currentSelectedNode = folderTreeNode; 50 } 51 52 initialFolderTree(); 53 updateFolderTree(currentSelectedNode); 54 55 //以下処理をやってもSelectedNodeは変わらずnullになる 56 //TreeNode tmp = folderTree.SelectedNode; //現在のSelectedNodeを一時保管 57 //folderTree.Nodes.Clear(); //TreeNodeを初期化 58 //updateFolderTree(currentSelectedNode); //TreeNode追加 59 //folderTree.SelectedNode = tmp; //一時保管していたNodeを再格納 60 // 61 62 String key = currentDirectoryPath.ToString().Replace("\\", "\"); 63 //↓↓↓↓↓↓↓↓↓↓↓↓↓↓エラー発生場所↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 64 //TreeNode[] nextSelectedNode = folderTree.Nodes.Find(key, true); だとnameプロパティで探す→検索結果はゼロ 65 //※以下サイトを参考にTextプロパティで探せるようにしても検索結果はゼロ 66 //「Is there a method for searching for TreeNode.Text field in TreeView.Nodes collection?」 67 //(http://stackoverflow.com/questions/12388249/is-there-a-method-for-searching-for-treenode-text-field-in-treeview-nodes-collec) 68 TreeNode[] nextSelectedNode = folderTreeNode.Nodes.Cast<TreeNode>().Where(r => r.Text == key).ToArray(); 69 folderTree.SelectedNode = nextSelectedNode[0]; 70 //↑↑↑↑↑↑↑↑↑↑↑↑↑↑エラー発生場所↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 71 72 String beforePath = currentDirectoryPath.ToString().Replace("\\", "\"); 73 Button clickedButton = sender as Button; 74 String afterPath = clickedButton.Name.ToString().Replace("\\", "\"); 75 76 updateAddressBar(afterPath); 77 78 if (beforePath != null) 79 { 80 81 String diff = beforePath.Replace(afterPath, ""); 82 int depth = diff.Split('\').Count(); 83 for (int i = 0; i < depth; i++) 84 { 85 if (folderTree.SelectedNode == null) 86 { 87 folderTree.SelectedNode = currentSelectedNode; 88 } 89 folderTree.SelectedNode = folderTree.SelectedNode.Parent; 90 } 91 folderTree.Focus(); 92 } 93 } 94 #endregion 95 96 97 /* 98 *フォルダツリーの初期化(ドライブ一覧) 99 */ 100 private void initialFolderTree() 101 { 102 folderTree.Nodes.Clear();//SelectedNodeがクリアされる 103 104 foreach (String driveName in Environment.GetLogicalDrives()) 105 { 106 folderTreeNode = new TreeNode(driveName, 0, 0); 107 folderTreeNode.Name = driveName; 108 folderTree.Nodes.Add(folderTreeNode); 109 folderTreeNode.Nodes.Add("..."); 110 } 111 folderTree.Sorted = true; //文字列順に自動Sort 112 } 113 114 115 /* 116 *選択されたノードに応じてフォルダツリーを更新 117 */ 118 private void updateFolderTree(TreeNode currentNode) 119 { 120 121 //folderTreeNode = currentNode; 122 String nodePath = null; 123 try 124 { 125 nodePath = currentNode.FullPath; 126 currentDirectoryPath = nodePath; 127 } 128 catch(InvalidOperationException e) 129 { 130 nodePath = currentDirectoryPath; 131 } 132 currentNode.Nodes.Clear(); 133 134 if (System.IO.Directory.Exists(nodePath)) 135 { 136 DirectoryInfo directoryInfo = new DirectoryInfo(nodePath); 137 138 try 139 { 140 DirectoryInfo[] directoryList = directoryInfo.GetDirectories(); 141 if (directoryList.Count() != 0) 142 { 143 DirectoryInfo[] directoryInfoList = directoryInfo.GetDirectories(); 144 String root = currentDirectoryPath.ToString().Substring(0, 1); 145 foreach (DirectoryInfo childDirectoryInfo in directoryInfoList) 146 { 147 folderTreeNode = new TreeNode(childDirectoryInfo.Name); 148 folderTreeNode.Name = childDirectoryInfo.FullName; 149 currentNode.Nodes.Add(folderTreeNode); 150 folderTreeNode.Nodes.Add("..."); 151 } 152 } 153 folderTreeNode = currentNode; 154 155 updatePicturePanel(directoryInfo); 156 updateAddressBar(directoryInfo.FullName); 157 } 158 catch (UnauthorizedAccessException){} 159 } 160 } 161 162 /* 163 * アドレスバーの更新 164 */ 165 private void updateAddressBar(String fullPath) 166 { 167 String[] arraypath = fullPath.Replace("\\", "\").Split('\'); 168 addressBar.Controls.Clear(); 169 currentDirectoryPath = arraypath[0] + '\'; 170 foreach (String path in arraypath) 171 { 172 if (currentDirectoryPath != path + '\') 173 { 174 currentDirectoryPath += ('\' + path); 175 } 176 Button button = new Button(); 177 button.Text = path; //後でフルパスが取得できるようにしておく 178 button.Click += new EventHandler(folderTree_Update); 179 button.MinimumSize = new Size(10, 23); 180 button.MaximumSize = new Size(50, 23); 181 button.Name = currentDirectoryPath; 182 addressBar.Controls.Add(button); 183 } 184 progressText.Text = fullPath; 185 186 } 187}
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。