avaloniauiavalonia

TreeView data binding to another control


I have a TreeView that uses data binding to render itself.

When a given node in the TreeView is selected, I want to update a TextBox with that node's data.

When the user edits the text in the TextBox, I want the selected node's data automatically updated.

For this scenario, data binding to a completely different control, I have no idea where to even start.

If anyone could furnish a reference, that would be great!

In other words, I'd like to replace these lines:

https://github.com/EricTerrell/Vault3.Desktop.Avalonia.Prototype/blob/main/Vault3.Desktop.Avalonia.Prototype/MainApplicationWindow.axaml.cs#L40-L51

with data binding markup in MainApplicationWindow.axaml, if that's not too painful.

GitHub repo: https://github.com/EricTerrell/Vault3.Desktop.Avalonia.Prototype

Chat GPT's answer is not very appealing (lots of code and markup to replace those 11 lines of code):

https://chatgpt.com/share/689287fb-7594-800b-8c0d-0ead4d4a633d (Note: I haven't verified that it works)


Solution

  • It could be solved by a DependencyProperty but following the MVVM path is recommended as the whole nature of these XAML stuff (WPF, MAUI, Avalonia, ...) is MVVM.

    Starting with a ViewModel for the Window with two properties for the nodes and the current selected node. (Used the nuget package CommunityToolkit.MVVM)

    public partial class MainApplicationWindowModel : ObservableObject
    {
        public ObservableCollection<OutlineItem> Nodes { get; } =
        [
            new OutlineItem( "Animals", "animals are nice",
            [
                new OutlineItem( "Mammals", "mammals are nice",
                [
                    new OutlineItem( "Lion", "Lions are nice" ),
                    new OutlineItem( "Cat", "Cats are nice" ),
                    new OutlineItem( "Zebra", "Zebras are nice" )
                ] )
            ] )
        ];
    
        [ObservableProperty] public partial OutlineItem? CurrentNode { get; set; }
    }
    

    The window needs some modifications

    <!-- setting the data type -->
    <Window 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:prototype="clr-namespace:Vault3.Desktop.Avalonia.Prototype"
            mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
    
            x:DataType="prototype:MainApplicationWindowModel"
    
            x:Class="Vault3.Desktop.Avalonia.Prototype.MainApplicationWindow"
            Title="Vault 3"
            >
    <!-- setting the data context -->
        <Window.DataContext>
            <prototype:MainApplicationWindowModel/>
        </Window.DataContext>
    <!-- [...] -->
    <!-- binding the treeview to the vm properties -->
                        <TreeView
                            Name="Treeview"
                            SelectedItem="{Binding CurrentNode}"
                            ItemsSource="{Binding Nodes}"
    <!-- [...] -->
    <!-- binding the text box with the current node -->
                <TextBox
                    Name="Text"
                    Text="{Binding CurrentNode.Text}"
    <!-- [...] -->
    

    This will push the edits in the text box back to the selected node. But you might want the OutlineItem also observable.

    public partial class OutlineItem : ObservableObject
    {
        public ObservableCollection<OutlineItem>? SubNodes { get; }
        [ObservableProperty] public partial string Title { get; set; }
        [ObservableProperty] public partial string Text { get; set; }
      
        public OutlineItem(string title, string text)
        {
            Title = title;
            Text = text;
        }
    
        public OutlineItem(string title, string text, ObservableCollection<OutlineItem> subNodes)
        {
            Title = title;
            Text = text;
            SubNodes = subNodes;
        }
    }