I am trying to bind an observable collection of rectangles to an items control with a canvas as the item panel, but there seems to be no way of binding the Canvas.Left
and Canvas.Top
properties to the Rectangle items. I attempted to do this by adding a ItemsControl.ItemContainerStyle like one would in WPF, but this doesn't seem to exist in Avalonia.
I searched and found this: https://github.com/AvaloniaUI/Avalonia/discussions/10018
However, I couldn't find any reference to ItemContainerTheme on the Avalonia documentation.
This is what I have currently:
<ItemsControl Grid.Row="1" Items="{Binding Rectangles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Red" Width="{Binding Width}" Height="{Binding Height}"></Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is the view model for each item that the items template is binding to:
public class RectangleViewModel : ViewModelBase
{
private int _x = 0;
public int X
{
get => _x;
set => this.RaiseAndSetIfChanged(ref _x, value);
}
private int _y = 0;
public int Y
{
get => _y;
set => this.RaiseAndSetIfChanged(ref _y, value);
}
private int _width = 0;
public int Width
{
get => _width;
set => this.RaiseAndSetIfChanged(ref _width, value);
}
private int _height = 0;
public int Height
{
get => _height;
set => this.RaiseAndSetIfChanged(ref _height, value);
}
}
And this is my Rectangles collection:
public ObservableCollection<RectangleViewModel> Rectangles { get; } = new();
Solved. I managed to find a somewhat related Github issue here https://github.com/AvaloniaUI/Avalonia/issues/2302 that uses the attached Styles
attribute to add the Canvas.Left
and Canvas.Top
properties.
The fixed result:
<ItemsControl Grid.Row="1" Items="{Binding Rectangles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Styles>
<Style Selector="ItemsControl > ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.Styles>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Stroke="#00FF00" StrokeThickness="2" Fill="Transparent" Width="{Binding Width}" Height="{Binding Height}"></Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>