WIP: start to implement template.

This commit is contained in:
rabbitism
2025-09-12 16:28:15 +08:00
parent fa7891297b
commit 452e118644
4 changed files with 111 additions and 2 deletions

View File

@@ -0,0 +1,67 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa">
<!-- Add Resources Here -->
<ControlTheme x:Key="{x:Type u:MultiAutoCompleteBox}" TargetType="u:MultiAutoCompleteBox">
<Setter Property="Template">
<ControlTemplate TargetType="u:MultiAutoCompleteBox">
<Panel>
<Border
Name="PART_RootBorder"
MinHeight="30"
Padding="{DynamicResource TextBoxContentPadding}"
VerticalAlignment="Stretch"
Background="{DynamicResource TextBoxDefaultBackground}"
BorderBrush="{DynamicResource TextBoxDefaultBorderBrush}">
<ItemsControl
Name="{x:Static u:MultiAutoCompleteBox.PART_SelectedItemsControl}"
ItemsSource="{TemplateBinding SelectedItems}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- TODO: Update command. -->
<u:ClosableTag
Content="{Binding .}"
Command="{Binding $parent[u:TagInput].Close}"
ContentTemplate="{TemplateBinding SelectedItemTemplate}"
></u:ClosableTag>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<u:WrapPanelWithTrailingItem>
<u:WrapPanelWithTrailingItem.TrailingItem>
<TextBox VerticalAlignment="Center" Theme="{DynamicResource TagInputTextBoxTheme}"/>
</u:WrapPanelWithTrailingItem.TrailingItem>
</u:WrapPanelWithTrailingItem>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
<Popup
Name="PART_Popup"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
IsLightDismissEnabled="True"
PlacementTarget="{TemplateBinding}">
<Border
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
Margin="{DynamicResource AutoCompleteBoxPopupMargin}"
Padding="{DynamicResource AutoCompleteBoxPopupPadding}"
HorizontalAlignment="Stretch"
Background="{DynamicResource AutoCompleteBoxPopupBackground}"
BorderBrush="{DynamicResource AutoCompleteBoxPopupBorderBrush}"
BorderThickness="{DynamicResource AutoCompleteBoxPopupBorderThickness}"
BoxShadow="{DynamicResource AutoCompleteBoxPopupBoxShadow}"
CornerRadius="{DynamicResource AutoCompleteBoxPopupCornerRadius}">
<ListBox
Name="PART_SelectingItemsControl"
Foreground="{TemplateBinding Foreground}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Border>
</Popup>
</Panel>
</ControlTemplate>
</Setter>
</ControlTheme>
</ResourceDictionary>

View File

@@ -29,6 +29,7 @@
<ResourceInclude Source="Loading.axaml" />
<ResourceInclude Source="Marquee.axaml" />
<ResourceInclude Source="MessageBox.axaml" />
<ResourceInclude Source="MultiAutoCompleteBox.axaml" />
<ResourceInclude Source="MultiComboBox.axaml" />
<ResourceInclude Source="NavMenu.axaml" />
<ResourceInclude Source="Notification.axaml" />

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using Avalonia;
@@ -173,16 +174,39 @@ public partial class MultiAutoCompleteBox
public static readonly StyledProperty<object?> InnerRightContentProperty =
TextBox.InnerRightContentProperty.AddOwner<MultiAutoCompleteBox>();
/// <summary>
/// Defines the <see cref="SelectedItems"/> property
/// </summary>
public static readonly StyledProperty<IList?> SelectedItemsProperty =
AvaloniaProperty.Register<MultiAutoCompleteBox, IList?>(
nameof(SelectedItems));
/// <summary>
/// Gets or sets the currently selected items. It is recommended to use an <see cref="ObservableCollection{T}"/>.
/// This property must be initialized from ViewModel.
/// </summary>
public IList? SelectedItems
{
get => GetValue(SelectedItemsProperty);
set => SetValue(SelectedItemsProperty, value);
}
/// <summary>
/// Identifies the <see cref="SelectedItemTemplate" /> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate?> SelectedItemTemplateProperty =
AvaloniaProperty.Register<MultiAutoCompleteBox, IDataTemplate?>(nameof(SelectedItemTemplate));
/// <summary>
/// Gets or sets the <see cref="T:Avalonia.DataTemplate" /> used to display each item in SelectedItems.
/// </summary>
[InheritDataTypeFromItems(nameof(SelectedItems))]
public IDataTemplate? SelectedItemTemplate
{
get => GetValue(SelectedItemTemplateProperty);
set => SetValue(SelectedItemTemplateProperty, value);
}
/// <summary>
/// Gets or sets the caret index
/// </summary>

View File

@@ -576,6 +576,16 @@ public partial class MultiAutoCompleteBox : TemplatedControl, IInnerContentContr
if (IsDropDownOpen && DropDownPopup != null && !DropDownPopup.IsOpen) OpeningDropDown(false);
base.OnApplyTemplate(e);
_selectedItemsControl = e.NameScope.Find<ItemsControl>(PART_SelectedItemsControl);
}
public const string PART_SelectedItemsControl = "PART_SelectedItemsControl";
private ItemsControl? _selectedItemsControl;
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
var textbox = (_selectedItemsControl?.ItemsPanelRoot as WrapPanelWithTrailingItem)?.TrailingItem as TextBox;
}
/// <summary>
@@ -590,7 +600,7 @@ public partial class MultiAutoCompleteBox : TemplatedControl, IInnerContentContr
BindingValueType state,
Exception? error)
{
if (property == TextProperty || property == SelectedItemProperty)
if (property == TextProperty)
{
DataValidationErrors.SetError(this, error);
}
@@ -1257,12 +1267,15 @@ public partial class MultiAutoCompleteBox : TemplatedControl, IInnerContentContr
}
else
{
// TODO implement selection.
/*
SearchText = string.Empty;
if (SelectedItem != null) _skipSelectedItemTextUpdate = true;
SetCurrentValue(SelectedItemProperty, null);
if (IsDropDownOpen) SetCurrentValue(IsDropDownOpenProperty, false);
*/
}
}
@@ -1529,8 +1542,11 @@ public partial class MultiAutoCompleteBox : TemplatedControl, IInnerContentContr
// Update the selected item property
// TODO set selection.
/*
if (SelectedItem != newSelectedItem) _skipSelectedItemTextUpdate = true;
SetCurrentValue(SelectedItemProperty, newSelectedItem);
*/
// Restore updates for TextSelection
if (_ignoreTextSelectionChange)
@@ -1612,7 +1628,8 @@ public partial class MultiAutoCompleteBox : TemplatedControl, IInnerContentContr
/// <param name="e">The selection changed event data.</param>
private void OnAdapterSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
SetCurrentValue(SelectedItemProperty, _adapter!.SelectedItem);
// TODO set selection.
// SetCurrentValue(SelectedItemProperty, _adapter!.SelectedItem);
}
//TODO Check UpdateTextCompletion