🦔

AvaloniaUI TreeViewの使い方

2024/02/23に公開

やりたいこと

Visual Studio 2022 + AvaloniaUI環境でTreeViewを使いたい。

使用環境

Windows 11 : Home 22H2 + Visual Studio Community 2022(64bit)
Linuxテスト環境 : 上記Windows上のWSL2 Ubuntsu 22.04.2 LTS
Visual Studio2022, AvaloniaUI 11.0.2

公式ドキュメント

下記に公式ドキュメントがあるが、いろいろな前提が省略されているので初めて使うとき
は結構こまった。
https://docs.avaloniaui.net/docs/reference/controls/detailed-reference/treeview-1

下記も参考にした
https://www.nequalsonelifestyle.com/2019/06/18/avalonia-treeview-tutorial/

実装詳細

Nodeクラスの作成

まずTreeViewのNodeとなるNodeクラスを作る。
下位のノードをSubNodeプロパティとして保持し、ObservableCollection<Node>?型にする。表示名称としてTitleプロパティを準備する。

namespace TestApp.Models
{
    public class Node
    {
        public ObservableCollection<Node>? SubNodes { get; }
        public string Title { get; }

        public Node(string title)
        {
            Title = title;
        }

        public Node(string title, ObservableCollection<Node> subNodes)
        {
            Title = title;
            SubNodes = subNodes;
        }
    }
}

ViewModelを作る

TreeView本体のViewModelクラスを作る。ここではProjectViewという名称でTreeViewを作っているので、ProjectViewModelという名称のクラスを作っている。
保持するNodeとしてObservableCollection<Node> Nodesをプロパティとして持たせている。コンストラクタで仮Nodeデータを作ってNodesを初期化している。

namespace TestApp.ViewModels
{
    public class ProjectViewModel : ViewModelBase
    {
        public ObservableCollection<Node> Nodes { get; }

        public ProjectViewModel()
        {
            Nodes = new ObservableCollection<Node>
            {
                new Node("Animals", new ObservableCollection<Node>
                {
                    new Node("Mammals", new ObservableCollection<Node>
                    {
                        new Node("Lion"), new Node("Cat"), new Node("Zebra")
                    })
                })
            };
        }
    }
}

xamlでTreeViewを作る

xaml全体は下記のようになった

ProjectView.axaml
<UserControl
	xmlns="https://github.com/avaloniaui"
	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:vm="clr-namespace:TestApp.ViewModels"
	xmlns:views="clr-namespace:TestApp.Views"
			 
	mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
	x:Class="TestApp.Views.ProjectView"
	x:DataType="vm:ProjectViewModel"
	>
	<Design.DataContext>
		<!-- This only sets the DataContext for the previewer in an IDE,
         to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
		<vm:ProjectViewModel />
	</Design.DataContext>
	<TreeView ItemsSource="{Binding Nodes}">
		<TreeView.ItemTemplate>
			<TreeDataTemplate ItemsSource="{Binding SubNodes}">
				<TextBlock Text="{Binding Title}"/>
			</TreeDataTemplate>
		</TreeView.ItemTemplate>
	</TreeView>
</UserControl>

xmlのネームスペース定義

まず vm = ViewModelとviews = Viewのnamespace定義をする

	xmlns:vm="clr-namespace:TestApp.ViewModels"
	xmlns:views="clr-namespace:TestApp.Views"

IDE用DataContextの宣言

TreeViewのBindingはDataContextの内容に対して行われる。IDEにDataContextを認識させるために下記のようにTestApp.ViewModels.ProjectViewModelをDataContextとして宣言する。
ただし、下記のコメントに記載されている通り、これはあくまでIDE用の宣言であり、コードでも別途DataContextの初期化が必要。これをやらないとProjectViewModelに対するインテリセンスが効かない。

	<Design.DataContext>
		<!-- This only sets the DataContext for the previewer in an IDE,
         to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
		<vm:ProjectViewModel />
	</Design.DataContext>

クラスとデータタイプを設定。

	x:Class="TestApp.Views.ProjectView"
	x:DataType="vm:ProjectViewModel"

TreeViewの宣言

ItemTemplete内でNodeに対するインテリセンスが効かない。けど動く。
ItemTemplateにもインテリセンスを効かせられないかいろいろやったけど、うまく動かすことができなかった。

	<TreeView ItemsSource="{Binding Nodes}">
		<TreeView.ItemTemplate>
			<TreeDataTemplate ItemsSource="{Binding SubNodes}">
				<TextBlock Text="{Binding Title}"/>
			</TreeDataTemplate>
		</TreeView.ItemTemplate>
	</TreeView>

DataContextの設定

ViewModelはprojectview.axaml.csで定義する必要がある

using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using RtlEditor2.ViewModels;
using System.Collections.ObjectModel;

namespace TestApp.Views
{
    public partial class ProjectView : UserControl
    {
        public ProjectView()
        {
            InitializeComponent();
            DataContext = new ProjectViewModel();
        }
    }
}

さらに詳細な実装

アイコン追加したり、各種イベント/プロパティの処理を追加するやり方は以下参照
https://zenn.dev/ajkfds/articles/bdbc6e074b4f52

Discussion