Merge pull request #749 from Samuel-B-D/fix-multicombobox-items-in-axaml

Fix MultiComboBox to works with items added in axaml
This commit is contained in:
Dong Bin
2025-08-29 01:30:52 +08:00
committed by GitHub
5 changed files with 107 additions and 29 deletions

View File

@@ -11,37 +11,56 @@
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="vm:MultiComboBoxDemoViewModel" x:DataType="vm:MultiComboBoxDemoViewModel"
mc:Ignorable="d"> mc:Ignorable="d">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Vertical">
<TextBlock>Binded ItemsSource</TextBlock>
<StackPanel Orientation="Horizontal">
<u:MultiComboBox
Watermark="Please Select"
Width="300"
MaxHeight="200"
SelectedItems="{Binding SelectedItems}"
ItemsSource="{Binding Items}" >
</u:MultiComboBox>
<u:MultiComboBox
Name="combo"
Watermark="Please Select"
Width="300"
InnerLeftContent="Left"
InnerRightContent="Right"
Classes="ClearButton"
MaxHeight="200"
SelectedItems="{Binding SelectedItems}"
ItemsSource="{Binding Items}" >
<u:MultiComboBox.PopupInnerTopContent>
<StackPanel Margin="0" Orientation="Horizontal">
<Button Theme="{DynamicResource BorderlessButton}" Content="Select All" Command="{Binding SelectAllCommand}"/>
<Button Theme="{DynamicResource BorderlessButton}" Content="Unselect All" Command="{Binding ClearAllCommand}"/>
<Button Theme="{DynamicResource BorderlessButton}" Content="Inverse" Command="{Binding InvertSelectionCommand}"/>
</StackPanel>
</u:MultiComboBox.PopupInnerTopContent>
<u:MultiComboBox.ContextFlyout>
<MenuFlyout>
<MenuItem Header="Select All" Command="{Binding SelectAllCommand}"/>
</MenuFlyout>
</u:MultiComboBox.ContextFlyout>
</u:MultiComboBox>
<ListBox ItemsSource="{Binding SelectedItems}" />
</StackPanel>
<Separator Margin="0 20" />
<TextBlock>Items inside axaml (u:MultiComboBox's tag content)</TextBlock>
<u:MultiComboBox <u:MultiComboBox
Watermark="Please Select" Watermark="Please Select"
Width="300" Width="300"
MaxHeight="200" MaxHeight="200">
SelectedItems="{Binding SelectedItems}" <u:MultiComboBoxItem>option 1</u:MultiComboBoxItem>
ItemsSource="{Binding Items}" > <u:MultiComboBoxItem>option 2</u:MultiComboBoxItem>
<u:MultiComboBoxItem>option 3</u:MultiComboBoxItem>
<u:MultiComboBoxItem><Button>option 4</Button></u:MultiComboBoxItem>
<Button>option 5</Button>
</u:MultiComboBox> </u:MultiComboBox>
<u:MultiComboBox
Name="combo"
Watermark="Please Select"
Width="300"
InnerLeftContent="Left"
InnerRightContent="Right"
Classes="ClearButton"
MaxHeight="200"
SelectedItems="{Binding SelectedItems}"
ItemsSource="{Binding Items}" >
<u:MultiComboBox.PopupInnerTopContent>
<StackPanel Margin="0" Orientation="Horizontal">
<Button Theme="{DynamicResource BorderlessButton}" Content="Select All" Command="{Binding SelectAllCommand}"/>
<Button Theme="{DynamicResource BorderlessButton}" Content="Unselect All" Command="{Binding ClearAllCommand}"/>
<Button Theme="{DynamicResource BorderlessButton}" Content="Inverse" Command="{Binding InvertSelectionCommand}"/>
</StackPanel>
</u:MultiComboBox.PopupInnerTopContent>
<u:MultiComboBox.ContextFlyout>
<MenuFlyout>
<MenuItem Header="Select All" Command="{Binding SelectAllCommand}"/>
</MenuFlyout>
</u:MultiComboBox.ContextFlyout>
</u:MultiComboBox>
<ListBox ItemsSource="{Binding SelectedItems}" />
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -135,7 +135,14 @@
Command="{TemplateBinding Command}" Command="{TemplateBinding Command}"
CommandParameter="{TemplateBinding}" CommandParameter="{TemplateBinding}"
Content="{StaticResource ClosableTagCloseIconGlyph}" /> Content="{StaticResource ClosableTagCloseIconGlyph}" />
<Border
IsVisible="{TemplateBinding VisualContent, Converter={x:Static ObjectConverters.IsNotNull}}"
Background="{TemplateBinding VisualContent}"
Width="{TemplateBinding VisualContentWidth}"
Height="{TemplateBinding VisualContentHeight}"
IsHitTestVisible="False" />
<ContentPresenter <ContentPresenter
IsVisible="{TemplateBinding VisualContent, Converter={x:Static ObjectConverters.IsNull}}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplate="{TemplateBinding ContentTemplate}"

View File

@@ -178,6 +178,19 @@ public class MultiComboBox : SelectingItemsControl, IInnerContentControl, IPopup
{ {
return new MultiComboBoxItem(); return new MultiComboBoxItem();
} }
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
{
if (item is MultiComboBoxItem containerItem)
{
container.DataContext = containerItem.Content;
return;
}
container.DataContext = item;
base.PrepareContainerForItemOverride(container, item, index);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
@@ -202,7 +215,7 @@ public class MultiComboBox : SelectingItemsControl, IInnerContentControl, IPopup
{ {
if (o is StyledElement s) if (o is StyledElement s)
{ {
var data = s.DataContext; var data = s is ClosableTag { VisualContent: not null } c ? c.Content : s.DataContext;
SelectedItems?.Remove(data); SelectedItems?.Remove(data);
var item = Items.FirstOrDefault(a => ReferenceEquals(a, data)); var item = Items.FirstOrDefault(a => ReferenceEquals(a, data));
if (item is not null) if (item is not null)

View File

@@ -1,6 +1,8 @@
using System.Windows.Input; using System.Windows.Input;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
namespace Ursa.Controls; namespace Ursa.Controls;
@@ -31,6 +33,15 @@ public class MultiComboBoxSelectedItemList: ItemsControl
if (container is ClosableTag tag) if (container is ClosableTag tag)
{ {
tag.Command = RemoveCommand; tag.Command = RemoveCommand;
if (item is Layoutable visualContent)
{
tag.VisualContent = new VisualBrush
{
Visual = visualContent,
};
tag.VisualContentWidth = visualContent.Bounds.Width;
tag.VisualContentHeight = visualContent.Bounds.Height;
}
} }
} }
} }

View File

@@ -2,6 +2,7 @@ using System.Windows.Input;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Media;
namespace Ursa.Controls; namespace Ursa.Controls;
@@ -12,10 +13,37 @@ public class ClosableTag : ContentControl
public static readonly StyledProperty<ICommand?> CommandProperty = AvaloniaProperty.Register<ClosableTag, ICommand?>( public static readonly StyledProperty<ICommand?> CommandProperty = AvaloniaProperty.Register<ClosableTag, ICommand?>(
nameof(Command)); nameof(Command));
public static readonly StyledProperty<VisualBrush?> VisualContentProperty = AvaloniaProperty.Register<ClosableTag, VisualBrush?>(
nameof(VisualContent));
public static readonly StyledProperty<double?> VisualContentWidthProperty = AvaloniaProperty.Register<ClosableTag, double?>(
nameof(VisualContentWidth));
public static readonly StyledProperty<double?> VisualContentHeightProperty = AvaloniaProperty.Register<ClosableTag, double?>(
nameof(VisualContentHeight));
public ICommand? Command public ICommand? Command
{ {
get => GetValue(CommandProperty); get => GetValue(CommandProperty);
set => SetValue(CommandProperty, value); set => SetValue(CommandProperty, value);
} }
public VisualBrush? VisualContent
{
get => GetValue(VisualContentProperty);
set => SetValue(VisualContentProperty, value);
}
public double? VisualContentWidth
{
get => GetValue(VisualContentWidthProperty);
set => SetValue(VisualContentWidthProperty, value);
}
public double? VisualContentHeight
{
get => GetValue(VisualContentHeightProperty);
set => SetValue(VisualContentHeightProperty, value);
}
} }