TreeViewでフォルダーを表現したいと思い試作してみます。
ファイル名:FolderItem.cs
using System.ComponentModel;
using Reactive.Bindings;
namespace TreeViewSample01;
public class FolderItem : INotifyPropertyChanged
{
// INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
// コンストラクタ
public FolderItem()
{
PropertyChanged += (s, e) => {};
}
// 名前
public ReactiveProperty<string> Name { get; set; } = new("");
// サブフォルダ
public ReactiveCollection<FolderItem> SubFolders { get; set; } = new();
}
ファイル名:MainWindow.xaml
<Window
x:Class="TreeViewSample01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewSample01"
mc:Ignorable="d"
Height="450"
Width="800"
FontSize="24"
xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<i:Interaction.Behaviors>
<local:ViewModelCleanupBehavior />
</i:Interaction.Behaviors>
<Grid>
<TreeView ItemsSource="{Binding Folders}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubFolders}">
<TextBlock Text="{Binding Name.Value}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
ファイル名:MainWindowViewModel.cs
using System.Diagnostics;
using System.ComponentModel;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Disposables;
namespace TreeViewSample01;
public class MainWindowViewModel : INotifyPropertyChanged, IDisposable
{
// INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
// IDisposable
private CompositeDisposable Disposable { get; } = [];
/**************************************************************************
* プロパティ
**************************************************************************/
public ReactiveCollection<FolderItem> Folders { get; set; } = [];
public MainWindowViewModel()
{
PropertyChanged += (s, e) => {};
var root = new FolderItem()
{
Name = new("/"),
};
Folders.AddOnScheduler(root);
var folderUser = new FolderItem()
{
Name = new("Users"),
};
root.SubFolders.AddOnScheduler(folderUser);
var folderBin = new FolderItem()
{
Name = new("Bin"),
};
folderUser.SubFolders.AddOnScheduler(folderBin);
var folderHome = new FolderItem()
{
Name = new("Home"),
};
root.SubFolders.AddOnScheduler(folderHome);
var folderEtc = new FolderItem()
{
Name = new("Etc"),
};
root.SubFolders.AddOnScheduler(folderEtc);
}
public void Dispose()
{
Debug.WriteLine("Dispose()");
Disposable.Dispose();
}
}
実行スクリーンショット
TreeViewのノードには子要素が複数存在します。ノードをフォルダーと見立てると子要素はサブフォルダーに相当し、コレクションで用意することになります。
ViewModelにReactiveCollection<FolderItem>を用意し、xamlのTreeViewのItemsSourceとバインドしています。
さらに、FolderItemクラスにはNameプロパティとSubFoldersコレクションを用意し、xamlのHierarchicalDataTemplateのItemsSourceにSubFolders、TextBlockにName.Valueをバインドしています。
ViewModelのコンストラクタでツリーの構造を作成しています。
TreeViewが作成できることが確認できました。次はTreeView側のイベント関連について調べたいと思います。
コメント