feat: improve demo.
This commit is contained in:
@@ -1,15 +1,55 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
x:Class="Ursa.Demo.Pages.SelectionListDemo"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:u="https://irihi.tech/ursa"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:vm="using:Ursa.Demo.ViewModels"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
x:DataType="vm:SelectionListDemoViewModel"
|
xmlns:u="https://irihi.tech/ursa"
|
||||||
x:CompileBindings="True"
|
xmlns:vm="using:Ursa.Demo.ViewModels"
|
||||||
mc:Ignorable="d" d:DesignWidth="800"
|
d:DesignHeight="450"
|
||||||
d:DesignHeight="450"
|
d:DesignWidth="800"
|
||||||
x:Class="Ursa.Demo.Pages.SelectionListDemo">
|
x:CompileBindings="True"
|
||||||
|
x:DataType="vm:SelectionListDemoViewModel"
|
||||||
|
mc:Ignorable="d">
|
||||||
<StackPanel HorizontalAlignment="Left">
|
<StackPanel HorizontalAlignment="Left">
|
||||||
<u:SelectionList ItemsSource="{Binding Items}"></u:SelectionList>
|
<u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
|
||||||
|
<u:SelectionList.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</u:SelectionList.ItemsPanel>
|
||||||
|
</u:SelectionList>
|
||||||
|
<u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />
|
||||||
|
<u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
|
||||||
|
<u:SelectionList.Indicator>
|
||||||
|
<Border Background="Transparent" CornerRadius="4">
|
||||||
|
<Border
|
||||||
|
Width="4"
|
||||||
|
Margin="0,8"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{DynamicResource SemiBlue6}"
|
||||||
|
CornerRadius="4" />
|
||||||
|
</Border>
|
||||||
|
</u:SelectionList.Indicator>
|
||||||
|
<u:SelectionList.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Panel Height="40">
|
||||||
|
<TextBlock
|
||||||
|
Classes.Active="{Binding $parent[u:SelectionListItem].IsSelected, Mode=OneWay}"
|
||||||
|
Margin="8,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{Binding}">
|
||||||
|
<TextBlock.Styles>
|
||||||
|
<Style Selector="TextBlock.Active">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Styles>
|
||||||
|
</TextBlock>
|
||||||
|
</Panel>
|
||||||
|
</DataTemplate>
|
||||||
|
</u:SelectionList.ItemTemplate>
|
||||||
|
</u:SelectionList>
|
||||||
|
<Button Command="{Binding Clear}">Clear</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||||||
|
|
||||||
namespace Ursa.Demo.ViewModels;
|
namespace Ursa.Demo.ViewModels;
|
||||||
|
|
||||||
public class SelectionListDemoViewModel: ObservableObject
|
public partial class SelectionListDemoViewModel: ObservableObject
|
||||||
{
|
{
|
||||||
public ObservableCollection<string> Items { get; set; }
|
public ObservableCollection<string> Items { get; set; }
|
||||||
|
[ObservableProperty] private string? _selectedItem;
|
||||||
|
|
||||||
public SelectionListDemoViewModel()
|
public SelectionListDemoViewModel()
|
||||||
{
|
{
|
||||||
@@ -14,4 +15,9 @@ public class SelectionListDemoViewModel: ObservableObject
|
|||||||
"Ding", "Otter", "Husky", "Mr. 17", "Cass"
|
"Ding", "Otter", "Husky", "Mr. 17", "Cass"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,19 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<ControlTheme x:Key="{x:Type u:SelectionList}" TargetType="u:SelectionList">
|
<ControlTheme x:Key="{x:Type u:SelectionList}" TargetType="u:SelectionList">
|
||||||
<Setter Property="Background" Value="LightBlue"></Setter>
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="Indicator">
|
||||||
|
<Template>
|
||||||
|
<Border
|
||||||
|
Margin="2"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{DynamicResource SemiBlue1}"
|
||||||
|
Theme="{DynamicResource CardBorder}" />
|
||||||
|
</Template>
|
||||||
|
</Setter>
|
||||||
<Setter Property="ListBox.Template">
|
<Setter Property="ListBox.Template">
|
||||||
<ControlTemplate TargetType="ListBox">
|
<ControlTemplate TargetType="u:SelectionList">
|
||||||
<Border
|
<Border
|
||||||
Name="border"
|
Name="border"
|
||||||
Background="{TemplateBinding Background}"
|
Background="{TemplateBinding Background}"
|
||||||
@@ -14,13 +24,7 @@
|
|||||||
ClipToBounds="{TemplateBinding ClipToBounds}"
|
ClipToBounds="{TemplateBinding ClipToBounds}"
|
||||||
CornerRadius="{TemplateBinding CornerRadius}">
|
CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
<Panel>
|
<Panel>
|
||||||
<Border
|
<ContentPresenter Name="{x:Static u:SelectionList.PART_Indicator}" Content="{TemplateBinding Indicator}" />
|
||||||
Classes="Shadow"
|
|
||||||
Margin="2"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Name="{x:Static u:SelectionList.PART_Indicator}"
|
|
||||||
Theme="{DynamicResource CardBorder}" />
|
|
||||||
<ItemsPresenter
|
<ItemsPresenter
|
||||||
Name="PART_ItemsPresenter"
|
Name="PART_ItemsPresenter"
|
||||||
Margin="{TemplateBinding Padding}"
|
Margin="{TemplateBinding Padding}"
|
||||||
@@ -33,20 +37,25 @@
|
|||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:SelectionListItem}" TargetType="u:SelectionListItem">
|
<ControlTheme x:Key="{x:Type u:SelectionListItem}" TargetType="u:SelectionListItem">
|
||||||
<Setter Property="Background" Value="Transparent" />
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||||
<Setter Property="Padding" Value="8" />
|
<Setter Property="Padding" Value="8" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:SelectionListItem">
|
<ControlTemplate TargetType="u:SelectionListItem">
|
||||||
<ContentPresenter
|
<ContentPresenter
|
||||||
Name="PART_ContentPresenter"
|
Name="PART_ContentPresenter"
|
||||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
Padding="{TemplateBinding Padding}"
|
Padding="{TemplateBinding Padding}"
|
||||||
Foreground="{TemplateBinding Foreground}"
|
|
||||||
Background="{TemplateBinding Background}"
|
Background="{TemplateBinding Background}"
|
||||||
Content="{TemplateBinding Content}"
|
Content="{TemplateBinding Content}"
|
||||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
FontWeight="{TemplateBinding FontWeight}"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||||
|
Foreground="{TemplateBinding Foreground}" />
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
<Style Selector="^:selected">
|
<Style Selector="^:selected">
|
||||||
<Setter Property="Foreground" Value="Blue"></Setter>
|
<Setter Property="FontWeight" Value="Bold" />
|
||||||
</Style>
|
</Style>
|
||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
|
using Avalonia.Controls.Presenters;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Selection;
|
using Avalonia.Controls.Selection;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
@@ -11,14 +13,23 @@ using Irihi.Avalonia.Shared.Helpers;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
[TemplatePart(PART_Indicator, typeof(Control))]
|
[TemplatePart(PART_Indicator, typeof(ContentPresenter))]
|
||||||
public class SelectionList: SelectingItemsControl
|
public class SelectionList: SelectingItemsControl
|
||||||
{
|
{
|
||||||
public const string PART_Indicator = "PART_Indicator";
|
public const string PART_Indicator = "PART_Indicator";
|
||||||
private static readonly FuncTemplate<Panel?> DefaultPanel = new(() => new StackPanel());
|
private static readonly FuncTemplate<Panel?> DefaultPanel = new(() => new StackPanel());
|
||||||
|
|
||||||
private Control? _indicator;
|
|
||||||
private ImplicitAnimationCollection? _implicitAnimations;
|
private ImplicitAnimationCollection? _implicitAnimations;
|
||||||
|
private ContentPresenter? _indicator;
|
||||||
|
|
||||||
|
public static readonly StyledProperty<Control?> IndicatorProperty = AvaloniaProperty.Register<SelectionList, Control?>(
|
||||||
|
nameof(Indicator));
|
||||||
|
|
||||||
|
public Control? Indicator
|
||||||
|
{
|
||||||
|
get => GetValue(IndicatorProperty);
|
||||||
|
set => SetValue(IndicatorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
static SelectionList()
|
static SelectionList()
|
||||||
{
|
{
|
||||||
@@ -75,25 +86,23 @@ public class SelectionList: SelectingItemsControl
|
|||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
_indicator = e.NameScope.Find<Control>(PART_Indicator);
|
_indicator= e.NameScope.Find<ContentPresenter>(PART_Indicator);
|
||||||
_indicator?.Arrange(new Rect());
|
EnsureIndicatorAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureIndicatorAnimation()
|
||||||
|
{
|
||||||
if (_indicator is not null)
|
if (_indicator is not null)
|
||||||
{
|
{
|
||||||
_indicator.Opacity = 0;
|
_indicator.Opacity = 0;
|
||||||
SetUpAnimation();
|
SetUpAnimation();
|
||||||
if (ElementComposition.GetElementVisual(_indicator) is { } v)
|
if (ElementComposition.GetElementVisual(_indicator) is { } v)
|
||||||
{
|
{
|
||||||
v.ImplicitAnimations = _implicitAnimations;
|
v.ImplicitAnimations = _implicitAnimations;
|
||||||
}
|
}
|
||||||
_indicator.SizeChanged += OnIndicatorSizeChanged;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnIndicatorSizeChanged(object sender, SizeChangedEventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void SelectByIndex(int index)
|
internal void SelectByIndex(int index)
|
||||||
{
|
{
|
||||||
using var operation = Selection.BatchUpdate();
|
using var operation = Selection.BatchUpdate();
|
||||||
@@ -103,13 +112,16 @@ public class SelectionList: SelectingItemsControl
|
|||||||
|
|
||||||
private void SetUpAnimation()
|
private void SetUpAnimation()
|
||||||
{
|
{
|
||||||
|
if (_implicitAnimations != null) return;
|
||||||
|
var compositorVisual = ElementComposition.GetElementVisual(this);
|
||||||
|
if (compositorVisual is null) return;
|
||||||
var compositor = ElementComposition.GetElementVisual(this)!.Compositor;
|
var compositor = ElementComposition.GetElementVisual(this)!.Compositor;
|
||||||
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
|
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
|
||||||
offsetAnimation.Target = "Offset";
|
offsetAnimation.Target = nameof(CompositionVisual.Offset);
|
||||||
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
|
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
|
||||||
offsetAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
offsetAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
||||||
var sizeAnimation = compositor.CreateVector2KeyFrameAnimation();
|
var sizeAnimation = compositor.CreateVector2KeyFrameAnimation();
|
||||||
sizeAnimation.Target = "Size";
|
sizeAnimation.Target = nameof(CompositionVisual.Size);
|
||||||
sizeAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
|
sizeAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
|
||||||
sizeAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
sizeAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
||||||
var opacityAnimation = compositor.CreateScalarKeyFrameAnimation();
|
var opacityAnimation = compositor.CreateScalarKeyFrameAnimation();
|
||||||
@@ -118,9 +130,19 @@ public class SelectionList: SelectingItemsControl
|
|||||||
opacityAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
opacityAnimation.Duration = TimeSpan.FromSeconds(0.3);
|
||||||
|
|
||||||
_implicitAnimations = compositor.CreateImplicitAnimationCollection();
|
_implicitAnimations = compositor.CreateImplicitAnimationCollection();
|
||||||
_implicitAnimations["Offset"] = offsetAnimation;
|
_implicitAnimations[nameof(CompositionVisual.Offset)] = offsetAnimation;
|
||||||
_implicitAnimations["Size"] = sizeAnimation;
|
_implicitAnimations[nameof(CompositionVisual.Size)] = sizeAnimation;
|
||||||
_implicitAnimations["Opacity"] = opacityAnimation;
|
_implicitAnimations[nameof(CompositionVisual.Opacity)] = opacityAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
var hotkeys = Application.Current!.PlatformSettings?.HotkeyConfiguration;
|
||||||
|
|
||||||
|
if (e.Key.ToNavigationDirection() is { } direction && direction.IsDirectional())
|
||||||
|
{
|
||||||
|
e.Handled |= MoveSelection(direction, WrapSelection);
|
||||||
|
}
|
||||||
|
base.OnKeyDown(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user