TreeViewとTreeViewItemを使ってフォルダをツリー表示して、選択フォルダのパスを取得したい、バインディングとか無しで
TreeView.Items
┣TreeViewItem.Items
┃ ︙
┣TreeViewItem.Items
┃ ┣TreeViewItem.Items
┃ ┃ ︙
┃ ┗TreeViewItem.Items
┗TreeViewItem.Items
┣TreeViewItem.Items
┣TreeViewItem.Items
┃ ︙
┗TreeViewItem.Items
TreeView、TreeViewItem、DirectoryInfo
この3つを使って作った
TreeViewのItemsには
TreeViewItemをたくさん入れることができる
TreeViewのItemsに何か一つでも入っていると▷が表示される
▷をクリックでツリーが展開される
DirectoryInfoクラス
System.IO.DirectoryInfo
フォルダのフルパスやサブフォルダ一覧とかを使える
github.com
xaml
<Grid>
<GridColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
</GridColumnDefinitions>
<TreeView Name="MyRoot"/>
<StackPanel GridColumn="1">
<Button Content="test" Name="ButtonTest" Click="ButtonTest_Click"/>
</StackPanel>
</Grid>
gridを縦分割して、TreeViewとButtonを追加しただけ
cs
using System.Windows;
using System.Windows.Controls;
namespace _20191010_TreeView3
{
<summary>
</summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var item = new DirectoryTreeItem(new System.IO.DirectoryInfo(@"D:\ブログ用"));
MyRoot.Items.Add(item);
}
private void ButtonTest_Click(object sender, RoutedEventArgs e)
{
var neko = (DirectoryTreeItem)MyRoot.Items[0];
var inu = (TreeViewItem)neko.Items[0];
var item = (DirectoryTreeItem)MyRoot.SelectedItem;
if (item == null) return;
string str = item.ToString();
string dir = item.DirectoryInfo.FullName;
}
}
public class DirectoryTreeItem : TreeViewItem
{
public readonly System.IO.DirectoryInfo DirectoryInfo;
private bool IsAdd;
private TreeViewItem Dummy;
public DirectoryTreeItem(System.IO.DirectoryInfo info)
{
DirectoryInfo = info;
Header = info.Name;
if (info.GetDirectories().Length > 0)
{
Dummy = new TreeViewItem();
Items.Add(Dummy);
}
this.Expanded += (s, e) =>
{
if (IsAdd) return;
AddSubDirectory();
};
}
public void AddSubDirectory()
{
Items.Remove(Dummy);
System.IO.DirectoryInfo[] directories = DirectoryInfo.GetDirectories();
for (int i = 0; i < directories.Length; i++)
{
var fileAttributes = directories[i].Attributes;
if ((fileAttributes & System.IO.FileAttributes.Hidden) == System.IO.FileAttributes.Hidden ||
(fileAttributes & System.IO.FileAttributes.System) == System.IO.FileAttributes.System)
{
continue;
}
Items.Add(new DirectoryTreeItem(directories[i]));
}
IsAdd = true;
}
public override string ToString()
{
return DirectoryInfo.FullName;
}
}
}
ルートに表示したいフォルダパスからDirectoryInfoを作成して、これをTreeViewItemを継承したDirectoryTreeItemクラスに渡して作成したのを、TreeViewのItemsに追加する
今回はDドライブにあるブログ用って名前のフォルダを表示するので
16行目で
var item = new DirectoryTreeItem(new System.IO.DirectoryInfo(@"D:\ブログ用"));
17行目で
MyRoot.Items.Add(item);
これで表示される
サブフォルダ用のTreeViewItemの作成するタイミング
▷をクリックして展開したときにしたかったので、展開時のイベントExpandedで行っているのが56行目
サブフォルダ用のItemは1回作れば十分なので、2回目以降の展開時は作成しないようにフラグでチェック
サブフォルダの存在を示す▷の表示
サブフォルダ用のItemを作成するのは、展開前だけど▷の表示だけはしたいので、仮(dummy)のTreeViewItemを1つ作成して、入れておくことで表示している、展開したときにdummyを削除
この選択状態で確認
TreeViewのSelectedItemプロパティをキャストして、DirectoryInfoのFullNameプロパティで選択フォルダのパス
"D:\\ブログ用\\作物\\スイートバジル"
が取得できた、28行目
参照したところ
dobon.net
blog.okazuki.jp
qiita.com
ダミーのTreeViewItemで▷を表示する方法はこちらから
日記
WPFってファイル選択のダイアログボックスはあるんだけど、フォルダ選択のダイアログはないんだよねえ、んでWPF フォルダダイアログとかでググると、Windows API Code Packっていうのを使う方法が見つかるので試してみると
こんなふうに見つかるので、ライセンスの表示をクリックすると
表示できません、ページが消滅しているみたいなので
web.archiveで見たら
web.archive.org
英語かあ…Google翻訳してみても
なんかいっぱい書いてある、フォルダ選択したいだけなのに…
他の方法でWindowsフォームを参照に追加してそれを使うとかもあるけど、フォルダ選択したいだけなのに、そんなめんどくさいことしたくない
良さそうなのはTreeViewとバインディングを使った方法があるけど、難しくてわからん
ってことで今回の方法になった、これでもフォルダ選択のダイアログボックスみたいなのできるんじゃないかなあ
関連記事
2019/10/13は3日後
gogowaten.hatenablog.com