From edb66a77201f2f5bc8a7badb51f59278aa1ffc5b Mon Sep 17 00:00:00 2001
From: Dong Bin <14807942+rabbitism@users.noreply.github.com>
Date: Mon, 22 Apr 2024 15:09:32 +0800
Subject: [PATCH] ComboBox: support different DataTemplate for selected item.
(#15420)
* feat: ComboBox: support different DataTemplate for selected item.
* feat: use coerce instead of multi binding.
* test: add multiple unit tests.
---
.../ControlCatalog/Pages/ComboBoxPage.xaml | 29 +++++++--
src/Avalonia.Controls/ComboBox.cs | 36 ++++++++++-
.../Controls/ComboBox.xaml | 5 +-
.../Controls/ComboBox.xaml | 3 +-
.../ComboBoxTests.cs | 64 +++++++++++++++++++
5 files changed, 127 insertions(+), 10 deletions(-)
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index eca2c4762c8..ab347ac30c4 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -12,8 +12,8 @@
+ WrapSelection
Inline Item 4
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -114,9 +136,6 @@
-
- WrapSelection
-
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index 78bb191e93b..f1cc84f7a4b 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -5,10 +5,12 @@
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
+using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
+using Avalonia.Metadata;
using Avalonia.Reactive;
using Avalonia.VisualTree;
@@ -71,6 +73,23 @@ public class ComboBox : SelectingItemsControl
///
public static readonly StyledProperty VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner();
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty SelectionBoxItemTemplateProperty =
+ AvaloniaProperty.Register(
+ nameof(SelectionBoxItemTemplate), defaultBindingMode: BindingMode.TwoWay, coerce: CoerceSelectionBoxItemTemplate);
+
+ private static IDataTemplate? CoerceSelectionBoxItemTemplate(AvaloniaObject obj, IDataTemplate? template)
+ {
+ if (template is not null) return template;
+ if(obj is ComboBox comboBox && template is null)
+ {
+ return comboBox.ItemTemplate;
+ }
+ return template;
+ }
private Popup? _popup;
private object? _selectionBoxItem;
@@ -159,6 +178,16 @@ public VerticalAlignment VerticalContentAlignment
set => SetValue(VerticalContentAlignmentProperty, value);
}
+ ///
+ /// Gets or sets the DataTemplate used to display the selected item. This has a higher priority than if set.
+ ///
+ [InheritDataTypeFromItems(nameof(ItemsSource))]
+ public IDataTemplate? SelectionBoxItemTemplate
+ {
+ get => GetValue(SelectionBoxItemTemplateProperty);
+ set => SetValue(SelectionBoxItemTemplateProperty, value);
+ }
+
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
@@ -322,7 +351,10 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
{
PseudoClasses.Set(pcDropdownOpen, change.GetNewValue());
}
-
+ else if (change.Property == ItemTemplateProperty)
+ {
+ CoerceValue(SelectionBoxItemTemplateProperty);
+ }
base.OnPropertyChanged(change);
}
@@ -433,7 +465,7 @@ private void UpdateSelectionBoxItem(object? item)
}
else
{
- if(ItemTemplate is null && DisplayMemberBinding is { } binding)
+ if(ItemTemplate is null && SelectionBoxItemTemplate is null && DisplayMemberBinding is { } binding)
{
var template = new FuncDataTemplate