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

View File

@@ -25,6 +25,27 @@ public class MultiComboBoxDemoViewModel: ObservableObject
"Kansas",
"Kentucky",
"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 -->
<ControlTheme x:Key="{x:Type u:MultiComboBox}" TargetType="u:MultiComboBox">
<Setter Property="Focusable" Value="True" />
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Background" Value="{DynamicResource ComboBoxSelectorBackground}" />
<Setter Property="CornerRadius" Value="{DynamicResource ComboBoxSelectorCornerRadius}" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Width" Value="300" />
<Setter Property="MaxDropdownHeight" Value="300" />
<Setter Property="MaxSelectionBoxHeight" Value="270"></Setter>
<Setter Property="MinHeight" Value="32" />
<Setter Property="Padding" Value="12 4" />
<Setter Property="BorderThickness" Value="1" />
@@ -26,33 +27,57 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="PART_RootGrid" ColumnDefinitions="*, Auto, 32">
<Grid Name="PART_RootGrid" ColumnDefinitions="Auto, *, Auto, Auto, 32">
<Border
Name="{x:Static u:MultiComboBox.PART_BackgroundBorder}"
Grid.Column="0"
Grid.ColumnSpan="3"
Grid.ColumnSpan="5"
Background="Transparent" />
<u:MultiComboBoxSelectedItemList
<ContentPresenter
Grid.Column="0"
Margin="8,0"
IsHitTestVisible="False"
VerticalAlignment="Center"
ItemsSource="{TemplateBinding SelectedItems}"
RemoveCommand="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Remove}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</u:MultiComboBoxSelectedItemList>
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"
ItemsSource="{TemplateBinding SelectedItems}"
RemoveCommand="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Remove}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</u:MultiComboBoxSelectedItemList>
</ScrollViewer>
<Button
Name="ClearButton"
Grid.Column="1"
Grid.Column="2"
Command="{Binding $parent[u:MultiComboBox].Clear}"
Content="{DynamicResource IconButtonClearData}"
IsVisible="False"
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
x:Name="DropDownGlyph"
Grid.Column="2"
Grid.Column="4"
Width="12"
Height="12"
Margin="0,0,10,0"
@@ -79,7 +104,10 @@
BoxShadow="{DynamicResource ComboBoxPopupBoxShadow}"
ClipToBounds="True"
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
Name="PART_ItemsPresenter"
Margin="{DynamicResource ComboBoxDropdownContentMargin}"
@@ -98,7 +126,7 @@
<Style Selector="^.Small">
<Setter Property="MinHeight" Value="{DynamicResource ComboBoxSmallHeight}" />
</Style>
<Style Selector="^.clearButton, ^.ClearButton">
<Style Selector="^:pointerover:not(:selection-empty) /template/ Button#ClearButton">
<Setter Property="IsVisible" Value="{Binding $parent[ComboBox].SelectionBoxItem, Converter={x:Static ObjectConverters.IsNotNull}}" />
@@ -186,13 +214,12 @@
<PathIcon
Name="CheckGlyph"
Grid.Column="0"
VerticalAlignment="Center"
Opacity="0"
Data="{DynamicResource ListBoxItemCheckCheckGlyph}"
Width="{DynamicResource ListBoxItemCheckBoxGlyphWidth}"
Height="{DynamicResource ListBoxItemCheckBoxGlyphHeight}"
Margin="8,0"
/>
VerticalAlignment="Center"
Data="{DynamicResource ListBoxItemCheckCheckGlyph}"
Opacity="0" />
<ContentPresenter
x:Name="ContentPresenter"
Grid.Column="1"
@@ -213,8 +240,7 @@
<Setter Property="Foreground" Value="{DynamicResource ListBoxItemDisabledForeground}" />
<Setter Property="Background" Value="{DynamicResource ListBoxItemDisabledBackground}" />
<Style Selector="^:selected">
<Setter Property="Background"
Value="{DynamicResource ListBoxItemSelectedDisabledBackground}" />
<Setter Property="Background" Value="{DynamicResource ListBoxItemSelectedDisabledBackground}" />
</Style>
</Style>
@@ -230,7 +256,7 @@
<!-- Selected State -->
<Style Selector="^:selected /template/ PathIcon#CheckGlyph">
<Setter Property="Opacity" Value="1"></Setter>
<Setter Property="Opacity" Value="1" />
</Style>
</ControlTheme>

View File

@@ -10,12 +10,13 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Irihi.Avalonia.Shared.Helpers;
using Irihi.Avalonia.Shared.Contracts;
namespace Ursa.Controls;
[TemplatePart(PART_BackgroundBorder, typeof(Border))]
[PseudoClasses(PC_DropDownOpen, PC_Empty)]
public class MultiComboBox: SelectingItemsControl
public class MultiComboBox: SelectingItemsControl, IInnerContentControl
{
public const string PART_BackgroundBorder = "PART_BackgroundBorder";
public const string PC_DropDownOpen = ":dropdownopen";
@@ -43,6 +44,15 @@ public class MultiComboBox: SelectingItemsControl
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?>(
nameof(SelectedItems), new AvaloniaList<object>());
@@ -51,6 +61,24 @@ public class MultiComboBox: SelectingItemsControl
get => GetValue(SelectedItemsProperty);
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()
{
@@ -139,7 +167,7 @@ public class MultiComboBox: SelectingItemsControl
public void Clear()
{
this.SelectedItems?.Clear();
// this.SelectedItems?.Clear();
var containers = Presenter?.Panel?.Children;
if(containers is null) return;
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)
{
base.OnUnloaded(e);