Search code examples
c#data-bindingavaloniauiavalonia

Getting stuck at simple Property Binding in Avalonia


I am at the very beginning of a simple application using Avalonia. I just tried to add a simple Data Binding for a List of Objects with one simple string property.

This is what the DataSources Class looks like:

public class ProcessName
{
    public string SomeThing { get; set; }
}

The axaml-File looks like this:

<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:linuxUi="clr-namespace:AutoShutDown.LinuxUi"
        xmlns:objectModel="clr-namespace:System.Collections.ObjectModel;assembly=System.ObjectModel"
        mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450"
        x:Class="AutoShutDown.LinuxUi.MainWindow"
        Title="AutoShutDown.LinuxUi"
        >
    <StackPanel>        
        <ListBox Name="ProcessList">
            <DataTemplate x:DataType="linuxUi:ProcessName">
                <StackPanel>
                    <TextBlock Text="{Binding SomeThing}"></TextBlock>
                
                </StackPanel>
            </DataTemplate>
        </ListBox>
    </StackPanel>
</Window>

(LinuxUI is my namespace)

the code behind only contains the binding:

public partial class MainWindow : Window
{
    public ObservableCollection<ProcessName> Processes { get; set; } 
    public MainWindow()
    {
        InitializeComponent();
        ProcessList.ItemsSource = Processes;
        ProcessList.Items.Add(new ProcessName {SomeThing = "Item 1"});
    }
}

Now not the property is shown but the following: output


Solution

  • You have added the DataTemplate as an item instead of assigning a value to the ItemTemplate property.

    The correct XAML looks like this:

    <ListBox x:Name="ProcessList">
        <ListBox.ItemTemplate>
            <DataTemplate x:DataType="linuxUi:ProcessName">
                <StackPanel>
                    <TextBlock Text="{Binding SomeThing}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    Or just

    <ListBox x:Name="ProcessList">
        <ListBox.ItemTemplate>
            <DataTemplate x:DataType="linuxUi:ProcessName">
                <TextBlock Text="{Binding SomeThing}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    Besides that, your Processes property is null and hence useless. The code behind should instead look like this:

    public ObservableCollection<ProcessName> Processes { get; } = [];
    // or for an older compiler:
    // public ObservableCollection<ProcessName> Processes { get; } = new ObservableCollection<ProcessName>();
    
    public MainView()
    {
        InitializeComponent();
        ProcessList.ItemsSource = Processes;
        Processes.Add(new ProcessName { SomeThing = "Item 1" });
    }
    

    You may now also bind the ItemsSource property in XAML:

    <ListBox ItemsSource="{Binding Processes,
        RelativeSource={RelativeSource AncestorType=Window}}">
    

    And remove the assignment in code behind:

    public MainView()
    {
        InitializeComponent();
        Processes.Add(new ProcessName { SomeThing = "Item 1" });
    }