Как в Avalonia правильно обработать событие раскрытия узла TreeView?

Всем привет! Недавно начал изучать Avalonia и столкнулся с проблемой обработки события раскрытия узла TreeView. У него есть событие TreeViewItem.Expanded="OnExpanded"

и обработчик

private void OnExpanded(object sender, RoutedEventArgs e)
{
    //...
}

Но в этом обработчике отсутствует e.OriginalSource (TreeViewItem, с которого раскрыли узел). А мне очень нужно знать какой узел был раскрыт.

В качестве узла использую класс:

public class Node {
    public Name {get; set;} // К примеру название директории
    public FullName {get; set;} // Полный путь к директории
    public ObservableCollection<Node> SubNodes {get; set;} // Подузлы
}

Вопрос к знатокам Avalonia и MVVM: допустимо ли вообще так решать эту задачу в MVVM? Или это нужно делать как-то через привязки?


Ответы (1 шт):

Автор решения: Николай

Разобрался. Делается это, как правильно сказал @EvgeniyZ по шаблону MVVM.

В файле MainWindow.axaml пишем:

//...
<Design.DataContext>
    <vm:MainWindowViewModel/>
</Design.DataContext>

<Grid>
    <TreeView ItemsSource="{Binding TreeViewNodes}">
        <TreeView.ItemTemplate>
            <TreeDataTemplate ItemsSource="{Binding SubNodes}">
                <TextBlock Text="{Binding Name}"/>
            </TreeDataTemplate>
        </TreeView.ItemTemplate>

        <TreeView.Styles>
            <Style Selector="TreeViewItem" x:DataType="models:Node">
                <!-- Привязываемся к раскрытию узла -->
                <Setter Property="IsExpanded" Value="{Binding IsExpanded}"/> 
            </Style>
        </TreeView.Styles>
    </TreeView>
<Grid>
//...

В файле ./ViewModels/MainWindowViewModel.cs

public partial class MainWindowViewModel : ViewModelBase
{
    public ObservableCollection<Node> TreeViewNodes { get; } = [];
    
    public MainWindowViewModel()
    {
        // Заполняем TreeViewNodes
    }
}

В ./Models/Node.cs

public sealed class Node: INotifyPropertyChanged
{
    public ObservableCollection<Node>? SubNodes { get; set; }
    
    public String Name { get; set; } = string.Empty;

    public String FullName { get; set; } = string.Empty;

    public Node(String name)
    {
        Name = name;
    }

    public Node(String name, ObservableCollection<Node> subNodes)
    {
        Name = name;
        SubNodes = subNodes;
    }
    
    private bool _isExpanded;
    
    public bool IsExpanded
    {
        get => _isExpanded;
        set
        {
            _isExpanded = value;

            // Реакция на разворачивание узла 

            OnPropertyChanged("IsExpanded");
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
→ Ссылка