diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index e9c959df6a..a2fb21330c 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -83,6 +83,7 @@ namespace Avalonia.Controls private int _itemCount; private ItemContainerGenerator? _itemContainerGenerator; private EventHandler? _childIndexChanged; + private IDataTemplate? _displayMemberItemTemplate; /// /// Initializes static members of the class. @@ -291,19 +292,19 @@ namespace Avalonia.Controls else if (item is not Visual) hcc.Header = item; - if (ItemTemplate is { } it) + if (GetEffectiveItemTemplate() is { } it) hcc.HeaderTemplate = it; } else if (container is ContentControl cc) { cc.Content = item; - if (ItemTemplate is { } it) + if (GetEffectiveItemTemplate() is { } it) cc.ContentTemplate = it; } else if (container is ContentPresenter p) { p.Content = item; - if (ItemTemplate is { } it) + if (GetEffectiveItemTemplate() is { } it) p.ContentTemplate = it; } } @@ -431,6 +432,17 @@ namespace Avalonia.Controls throw new NotImplementedException(); ////_itemContainerGenerator.ItemContainerTheme = change.GetNewValue(); } + else if (change.Property == ItemTemplateProperty) + { + if (change.NewValue is not null && DisplayMemberBinding is not null) + throw new InvalidOperationException("Cannot set both DisplayMemberBinding and ItemTemplate."); + } + else if (change.Property == DisplayMemberBindingProperty) + { + if (change.NewValue is not null && ItemTemplate is not null) + throw new InvalidOperationException("Cannot set both DisplayMemberBinding and ItemTemplate."); + _displayMemberItemTemplate = null; + } } /// @@ -568,6 +580,23 @@ namespace Avalonia.Controls } } + private IDataTemplate? GetEffectiveItemTemplate() + { + if (ItemTemplate is { } itemTemplate) + return itemTemplate; + + if (_displayMemberItemTemplate is null && DisplayMemberBinding is { } binding) + { + _displayMemberItemTemplate = new FuncDataTemplate((_, _) => + new TextBlock + { + [!TextBlock.TextProperty] = binding, + }); + } + + return _displayMemberItemTemplate; + } + /// /// Called when the changes. /// diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index 1eb13439a5..eeaef3c321 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -708,6 +708,31 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(container.Child!.GetValue(TextBlock.TextProperty), "3"); } + [Fact] + public void Cannot_Set_Both_DisplayMemberBinding_And_ItemTemplate_1() + { + var target = new ItemsControl + { + Template = GetTemplate(), + DisplayMemberBinding = new Binding("Length") + }; + + Assert.Throws(() => + target.ItemTemplate = new FuncDataTemplate((_, _) => new TextBlock())); + } + + [Fact] + public void Cannot_Set_Both_DisplayMemberBinding_And_ItemTemplate_2() + { + var target = new ItemsControl + { + Template = GetTemplate(), + ItemTemplate = new FuncDataTemplate((_, _) => new TextBlock()), + }; + + Assert.Throws(() => target.DisplayMemberBinding = new Binding("Length")); + } + private class Item { public Item(string value)