feat: add inner left/right support. add max box height.

This commit is contained in:
rabbitism
2024-03-27 16:04:57 +08:00
parent 5d917d5905
commit 35128295b3
4 changed files with 129 additions and 37 deletions

View File

@@ -1,15 +1,23 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl
x:Class="Ursa.Demo.Pages.MultiComboBoxDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:vm="using:Ursa.Demo.ViewModels"
xmlns:u="https://irihi.tech/ursa" xmlns:u="https://irihi.tech/ursa"
x:DataType="vm:MultiComboBoxDemoViewModel" xmlns:vm="using:Ursa.Demo.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True" x:CompileBindings="True"
x:Class="Ursa.Demo.Pages.MultiComboBoxDemo"> x:DataType="vm:MultiComboBoxDemoViewModel"
mc:Ignorable="d">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<u:MultiComboBox Classes="ClearButton" Name="combo" ItemsSource="{Binding Items}"/> <u:MultiComboBox
<ListBox ItemsSource="{Binding #combo.SelectedItems}"/> Name="combo"
InnerLeftContent="Left"
InnerRightContent="Right"
Classes="ClearButton"
ItemsSource="{Binding Items}" />
<ListBox ItemsSource="{Binding #combo.SelectedItems}" />
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -25,6 +25,27 @@ public class MultiComboBoxDemoViewModel: ObservableObject
"Kansas", "Kansas",
"Kentucky", "Kentucky",
"Louisiana", "Louisiana",
"Maine",
"Maryland",
"Massachusetts",
"Michigan",
"Minnesota",
"Mississippi",
"Missouri",
"Montana",
"Nebraska",
"Nevada",
"New Hampshire",
"New Jersey",
"New Mexico",
"New York",
"North Carolina",
"North Dakota",
"Ohio",
"Oklahoma",
"Oregon",
"Pennsylvania",
"Rhode Island",
}; };
} }
} }

View File

@@ -5,13 +5,14 @@
<!-- Add Resources Here --> <!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:MultiComboBox}" TargetType="u:MultiComboBox"> <ControlTheme x:Key="{x:Type u:MultiComboBox}" TargetType="u:MultiComboBox">
<Setter Property="Focusable" Value="True" /> <Setter Property="Focusable" Value="True" />
<Setter Property="VerticalAlignment" Value="Top"/> <Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Background" Value="{DynamicResource ComboBoxSelectorBackground}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxSelectorBackground}" />
<Setter Property="CornerRadius" Value="{DynamicResource ComboBoxSelectorCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ComboBoxSelectorCornerRadius}" />
<Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Width" Value="300" /> <Setter Property="Width" Value="300" />
<Setter Property="MaxDropdownHeight" Value="300" /> <Setter Property="MaxDropdownHeight" Value="300" />
<Setter Property="MaxSelectionBoxHeight" Value="270"></Setter>
<Setter Property="MinHeight" Value="32" /> <Setter Property="MinHeight" Value="32" />
<Setter Property="Padding" Value="12 4" /> <Setter Property="Padding" Value="12 4" />
<Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderThickness" Value="1" />
@@ -26,14 +27,28 @@
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"> CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="PART_RootGrid" ColumnDefinitions="*, Auto, 32"> <Grid Name="PART_RootGrid" ColumnDefinitions="Auto, *, Auto, Auto, 32">
<Border <Border
Name="{x:Static u:MultiComboBox.PART_BackgroundBorder}" Name="{x:Static u:MultiComboBox.PART_BackgroundBorder}"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="3" Grid.ColumnSpan="5"
Background="Transparent" /> Background="Transparent" />
<u:MultiComboBoxSelectedItemList <ContentPresenter
Grid.Column="0" Grid.Column="0"
Margin="8,0"
IsHitTestVisible="False"
VerticalAlignment="Center"
Content="{TemplateBinding InnerLeftContent}"
Foreground="{DynamicResource TextBoxInnerForeground}"
IsVisible="{TemplateBinding InnerLeftContent,
Converter={x:Static ObjectConverters.IsNotNull}}" />
<ScrollViewer
Grid.Column="1"
Grid.ColumnSpan="2"
MaxHeight="{TemplateBinding MaxSelectionBoxHeight}"
Background="{x:Null}"
HorizontalScrollBarVisibility="Disabled">
<u:MultiComboBoxSelectedItemList
VerticalAlignment="Center" VerticalAlignment="Center"
ItemsSource="{TemplateBinding SelectedItems}" ItemsSource="{TemplateBinding SelectedItems}"
RemoveCommand="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Remove}"> RemoveCommand="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Remove}">
@@ -43,16 +58,26 @@
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ItemsControl.ItemsPanel> </ItemsControl.ItemsPanel>
</u:MultiComboBoxSelectedItemList> </u:MultiComboBoxSelectedItemList>
</ScrollViewer>
<Button <Button
Name="ClearButton" Name="ClearButton"
Grid.Column="1" Grid.Column="2"
Command="{Binding $parent[u:MultiComboBox].Clear}" Command="{Binding $parent[u:MultiComboBox].Clear}"
Content="{DynamicResource IconButtonClearData}" Content="{DynamicResource IconButtonClearData}"
IsVisible="False" IsVisible="False"
Theme="{DynamicResource InnerIconButton}" /> Theme="{DynamicResource InnerIconButton}" />
<ContentPresenter
Grid.Column="3"
Margin="8,0"
VerticalAlignment="Center"
IsHitTestVisible="False"
Content="{TemplateBinding InnerRightContent}"
Foreground="{DynamicResource TextBoxInnerForeground}"
IsVisible="{TemplateBinding InnerRightContent,
Converter={x:Static ObjectConverters.IsNotNull}}" />
<PathIcon <PathIcon
x:Name="DropDownGlyph" x:Name="DropDownGlyph"
Grid.Column="2" Grid.Column="4"
Width="12" Width="12"
Height="12" Height="12"
Margin="0,0,10,0" Margin="0,0,10,0"
@@ -79,7 +104,10 @@
BoxShadow="{DynamicResource ComboBoxPopupBoxShadow}" BoxShadow="{DynamicResource ComboBoxPopupBoxShadow}"
ClipToBounds="True" ClipToBounds="True"
CornerRadius="6"> CornerRadius="6">
<ScrollViewer Grid.IsSharedSizeScope="True" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"> <ScrollViewer
Grid.IsSharedSizeScope="True"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
<ItemsPresenter <ItemsPresenter
Name="PART_ItemsPresenter" Name="PART_ItemsPresenter"
Margin="{DynamicResource ComboBoxDropdownContentMargin}" Margin="{DynamicResource ComboBoxDropdownContentMargin}"
@@ -186,13 +214,12 @@
<PathIcon <PathIcon
Name="CheckGlyph" Name="CheckGlyph"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center"
Opacity="0"
Data="{DynamicResource ListBoxItemCheckCheckGlyph}"
Width="{DynamicResource ListBoxItemCheckBoxGlyphWidth}" Width="{DynamicResource ListBoxItemCheckBoxGlyphWidth}"
Height="{DynamicResource ListBoxItemCheckBoxGlyphHeight}" Height="{DynamicResource ListBoxItemCheckBoxGlyphHeight}"
Margin="8,0" Margin="8,0"
/> VerticalAlignment="Center"
Data="{DynamicResource ListBoxItemCheckCheckGlyph}"
Opacity="0" />
<ContentPresenter <ContentPresenter
x:Name="ContentPresenter" x:Name="ContentPresenter"
Grid.Column="1" Grid.Column="1"
@@ -213,8 +240,7 @@
<Setter Property="Foreground" Value="{DynamicResource ListBoxItemDisabledForeground}" /> <Setter Property="Foreground" Value="{DynamicResource ListBoxItemDisabledForeground}" />
<Setter Property="Background" Value="{DynamicResource ListBoxItemDisabledBackground}" /> <Setter Property="Background" Value="{DynamicResource ListBoxItemDisabledBackground}" />
<Style Selector="^:selected"> <Style Selector="^:selected">
<Setter Property="Background" <Setter Property="Background" Value="{DynamicResource ListBoxItemSelectedDisabledBackground}" />
Value="{DynamicResource ListBoxItemSelectedDisabledBackground}" />
</Style> </Style>
</Style> </Style>
@@ -230,7 +256,7 @@
<!-- Selected State --> <!-- Selected State -->
<Style Selector="^:selected /template/ PathIcon#CheckGlyph"> <Style Selector="^:selected /template/ PathIcon#CheckGlyph">
<Setter Property="Opacity" Value="1"></Setter> <Setter Property="Opacity" Value="1" />
</Style> </Style>
</ControlTheme> </ControlTheme>

View File

@@ -10,12 +10,13 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Irihi.Avalonia.Shared.Helpers; using Irihi.Avalonia.Shared.Helpers;
using Irihi.Avalonia.Shared.Contracts;
namespace Ursa.Controls; namespace Ursa.Controls;
[TemplatePart(PART_BackgroundBorder, typeof(Border))] [TemplatePart(PART_BackgroundBorder, typeof(Border))]
[PseudoClasses(PC_DropDownOpen, PC_Empty)] [PseudoClasses(PC_DropDownOpen, PC_Empty)]
public class MultiComboBox: SelectingItemsControl public class MultiComboBox: SelectingItemsControl, IInnerContentControl
{ {
public const string PART_BackgroundBorder = "PART_BackgroundBorder"; public const string PART_BackgroundBorder = "PART_BackgroundBorder";
public const string PC_DropDownOpen = ":dropdownopen"; public const string PC_DropDownOpen = ":dropdownopen";
@@ -43,6 +44,15 @@ public class MultiComboBox: SelectingItemsControl
set => SetValue(MaxDropdownHeightProperty, value); set => SetValue(MaxDropdownHeightProperty, value);
} }
public static readonly StyledProperty<double> MaxSelectionBoxHeightProperty = AvaloniaProperty.Register<MultiComboBox, double>(
nameof(MaxSelectionBoxHeight));
public double MaxSelectionBoxHeight
{
get => GetValue(MaxSelectionBoxHeightProperty);
set => SetValue(MaxSelectionBoxHeightProperty, value);
}
public new static readonly StyledProperty<IList?> SelectedItemsProperty = AvaloniaProperty.Register<MultiComboBox, IList?>( public new static readonly StyledProperty<IList?> SelectedItemsProperty = AvaloniaProperty.Register<MultiComboBox, IList?>(
nameof(SelectedItems), new AvaloniaList<object>()); nameof(SelectedItems), new AvaloniaList<object>());
@@ -52,6 +62,24 @@ public class MultiComboBox: SelectingItemsControl
set => SetValue(SelectedItemsProperty, value); set => SetValue(SelectedItemsProperty, value);
} }
public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<MultiComboBox, object?>(
nameof(InnerLeftContent));
public object? InnerLeftContent
{
get => GetValue(InnerLeftContentProperty);
set => SetValue(InnerLeftContentProperty, value);
}
public static readonly StyledProperty<object?> InnerRightContentProperty = AvaloniaProperty.Register<MultiComboBox, object?>(
nameof(InnerRightContent));
public object? InnerRightContent
{
get => GetValue(InnerRightContentProperty);
set => SetValue(InnerRightContentProperty, value);
}
static MultiComboBox() static MultiComboBox()
{ {
FocusableProperty.OverrideDefaultValue<MultiComboBox>(true); FocusableProperty.OverrideDefaultValue<MultiComboBox>(true);
@@ -139,7 +167,7 @@ public class MultiComboBox: SelectingItemsControl
public void Clear() public void Clear()
{ {
this.SelectedItems?.Clear(); // this.SelectedItems?.Clear();
var containers = Presenter?.Panel?.Children; var containers = Presenter?.Panel?.Children;
if(containers is null) return; if(containers is null) return;
foreach (var container in containers) foreach (var container in containers)
@@ -151,6 +179,15 @@ public class MultiComboBox: SelectingItemsControl
} }
} }
public void SelectAll()
{
this.SelectedItems?.Clear();
foreach (var item in Items)
{
this.SelectedItems?.Add(item);
}
}
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
base.OnUnloaded(e); base.OnUnloaded(e);