mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-27 04:09:37 +08:00
Feature(Pagination): add QuickJumpEdit control
This commit is contained in:
@@ -76,7 +76,8 @@
|
||||
<StackPanel Spacing="20">
|
||||
<atom:Transfer ItemsSource="{Binding PaginationTransferItems}"
|
||||
IsOneWay="{Binding PaginationIsOneWay}"
|
||||
IsPaginationEnabled="True"/>
|
||||
IsPaginationEnabled="True"
|
||||
ListHeight="370"/>
|
||||
<atom:ToggleSwitch IsChecked="{Binding PaginationIsOneWay, Mode=TwoWay}"
|
||||
OnContent="ony way"
|
||||
OffContent="ony way"/>
|
||||
|
||||
+1
@@ -1170,6 +1170,7 @@ namespace AtomUI.Desktop.Controls.DesignTokens
|
||||
public static readonly TokenResourceKey ListHeight = new TokenResourceKey("AtomUI.Desktop.Controls.Transfer.ListHeight");
|
||||
public static readonly TokenResourceKey ListWidth = new TokenResourceKey("AtomUI.Desktop.Controls.Transfer.ListWidth");
|
||||
public static readonly TokenResourceKey ListWidthLG = new TokenResourceKey("AtomUI.Desktop.Controls.Transfer.ListWidthLG");
|
||||
public static readonly TokenResourceKey PaginationMargin = new TokenResourceKey("AtomUI.Desktop.Controls.Transfer.PaginationMargin");
|
||||
}
|
||||
|
||||
public static class TreeSelectTokenKey
|
||||
|
||||
@@ -77,7 +77,6 @@ public partial class ListView
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, TopPaginationAlignProperty, newPagination, AbstractPagination.AlignProperty));
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, IsHideOnSinglePageProperty, newPagination, AbstractPagination.IsHideOnSinglePageProperty));
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, IsEnabledProperty, newPagination, AbstractPagination.IsEnabledProperty));
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, SizeTypeProperty, newPagination, AbstractPagination.SizeTypeProperty));
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, IsMotionEnabledProperty, newPagination, AbstractPagination.IsMotionEnabledProperty));
|
||||
_topPaginationDisposables.Add(BindUtils.RelayBind(this, PaginationVisibilityProperty, newPagination, AbstractPagination.IsMotionEnabledProperty));
|
||||
_topPagination = newPagination;
|
||||
@@ -97,10 +96,9 @@ public partial class ListView
|
||||
{
|
||||
newPagination.CurrentPageChanged += HandlePageChangeRequest;
|
||||
_bottomPaginationDisposables = new CompositeDisposable();
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, TopPaginationAlignProperty, newPagination, AbstractPagination.AlignProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, BottomPaginationAlignProperty, newPagination, AbstractPagination.AlignProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, IsHideOnSinglePageProperty, newPagination, AbstractPagination.IsHideOnSinglePageProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, IsEnabledProperty, newPagination, AbstractPagination.IsEnabledProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, SizeTypeProperty, newPagination, AbstractPagination.SizeTypeProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, IsMotionEnabledProperty, newPagination, AbstractPagination.IsMotionEnabledProperty));
|
||||
_bottomPaginationDisposables.Add(BindUtils.RelayBind(this, PaginationVisibilityProperty, newPagination, AbstractPagination.IsMotionEnabledProperty));
|
||||
_bottomPagination = newPagination;
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using AtomUI.Collections;
|
||||
using AtomUI.Controls.Data;
|
||||
using AtomUI.Desktop.Controls.Primitives;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
@@ -356,7 +355,7 @@ internal class ListViewSelectionModel : SelectionModel<object?>, ISelectionModel
|
||||
{
|
||||
return l.IndexOf(item);
|
||||
}
|
||||
else if (source is ItemsSourceView v)
|
||||
if (source is ItemsSourceView v)
|
||||
{
|
||||
return v.IndexOf(item);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
<Style Selector="^ /template/ ContentPresenter#TopPaginationPresenter">
|
||||
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:ListViewTokenKey.PaginationMargin}}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#BottomPaginationPresenter">
|
||||
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:ListViewTokenKey.PaginationMargin}}"/>
|
||||
</Style>
|
||||
|
||||
@@ -97,17 +97,17 @@ public abstract class AbstractPagination : TemplatedControl, ISizeTypeAware, IMo
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly DirectProperty<AbstractPagination, bool> IsEffectiveHideOnSinglePageVisibleProperty =
|
||||
internal static readonly DirectProperty<AbstractPagination, bool> IsEffectiveVisibleProperty =
|
||||
AvaloniaProperty.RegisterDirect<AbstractPagination, bool>(
|
||||
nameof(IsEffectiveHideOnSinglePageVisible),
|
||||
o => o.IsEffectiveHideOnSinglePageVisible,
|
||||
(o, v) => o.IsEffectiveHideOnSinglePageVisible = v);
|
||||
nameof(IsEffectiveVisible),
|
||||
o => o.IsEffectiveVisible,
|
||||
(o, v) => o.IsEffectiveVisible = v);
|
||||
|
||||
private bool _isEffectiveHideOnSinglePageVisible = false;
|
||||
internal bool IsEffectiveHideOnSinglePageVisible
|
||||
private bool _isEffectiveVisible = false;
|
||||
internal bool IsEffectiveVisible
|
||||
{
|
||||
get => _isEffectiveHideOnSinglePageVisible;
|
||||
set => SetAndRaise(IsEffectiveHideOnSinglePageVisibleProperty, ref _isEffectiveHideOnSinglePageVisible, value);
|
||||
get => _isEffectiveVisible;
|
||||
set => SetAndRaise(IsEffectiveVisibleProperty, ref _isEffectiveVisible, value);
|
||||
}
|
||||
|
||||
private static bool PageSizeValidator(int pageSize)
|
||||
@@ -135,15 +135,23 @@ public abstract class AbstractPagination : TemplatedControl, ISizeTypeAware, IMo
|
||||
HandlePageConditionChanged();
|
||||
}
|
||||
if (change.Property == IsHideOnSinglePageProperty ||
|
||||
change.Property == PageCountProperty)
|
||||
change.Property == PageCountProperty ||
|
||||
change.Property == TotalProperty)
|
||||
{
|
||||
if (IsHideOnSinglePage)
|
||||
if (Total > 0)
|
||||
{
|
||||
SetValue(IsEffectiveHideOnSinglePageVisibleProperty, PageCount > 1);
|
||||
if (IsHideOnSinglePage)
|
||||
{
|
||||
SetValue(IsEffectiveVisibleProperty, PageCount > 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(IsEffectiveVisibleProperty, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(IsEffectiveHideOnSinglePageVisibleProperty, true);
|
||||
SetValue(IsEffectiveVisibleProperty, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace AtomUI.Desktop.Controls;
|
||||
|
||||
internal class QuickJumpEdit : LineEdit
|
||||
{
|
||||
public static readonly StyledProperty<int> MinimumProperty =
|
||||
AvaloniaProperty.Register<QuickJumpEdit, int>(nameof(Minimum), 1);
|
||||
|
||||
public static readonly StyledProperty<int> MaximumProperty =
|
||||
AvaloniaProperty.Register<QuickJumpEdit, int>(nameof(Maximum), int.MaxValue);
|
||||
|
||||
public int Minimum
|
||||
{
|
||||
get => GetValue(MinimumProperty);
|
||||
set => SetValue(MinimumProperty, value);
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get => GetValue(MaximumProperty);
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(LineEdit);
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == TextProperty)
|
||||
{
|
||||
if (int.TryParse(Text, out var pageNumber))
|
||||
{
|
||||
if (pageNumber < Minimum)
|
||||
{
|
||||
SetCurrentValue(TextProperty, Minimum.ToString());
|
||||
}
|
||||
|
||||
if (pageNumber > Maximum)
|
||||
{
|
||||
SetCurrentValue(TextProperty, Maximum.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTextInput(TextInputEventArgs e)
|
||||
{
|
||||
var inputText = e.Text?.Trim();
|
||||
if (!string.IsNullOrEmpty(inputText) && inputText.All(char.IsDigit))
|
||||
{
|
||||
base.OnTextInput(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class SimplePagination : AbstractPagination, IControlSharedTokenResources
|
||||
private PaginationNavItem? _previousPageItem;
|
||||
private PaginationNavItem? _nextPageItem;
|
||||
private TextBlock? _infoIndicator;
|
||||
private LineEdit? _quickJumper;
|
||||
private QuickJumpEdit? _quickJumper;
|
||||
|
||||
static SimplePagination()
|
||||
{
|
||||
@@ -53,7 +53,7 @@ public class SimplePagination : AbstractPagination, IControlSharedTokenResources
|
||||
_previousPageItem = e.NameScope.Find<PaginationNavItem>(SimplePaginationThemeConstants.PreviousNavItemPart);
|
||||
_nextPageItem = e.NameScope.Find<PaginationNavItem>(SimplePaginationThemeConstants.NextNavItemPart);
|
||||
_infoIndicator = e.NameScope.Find<TextBlock>(SimplePaginationThemeConstants.InfoIndicatorPart);
|
||||
_quickJumper = e.NameScope.Find<LineEdit>(SimplePaginationThemeConstants.QuickJumperPart);
|
||||
_quickJumper = e.NameScope.Find<QuickJumpEdit>(SimplePaginationThemeConstants.QuickJumperPart);
|
||||
|
||||
Debug.Assert(_nextPageItem != null);
|
||||
Debug.Assert(_previousPageItem != null);
|
||||
@@ -96,10 +96,25 @@ public class SimplePagination : AbstractPagination, IControlSharedTokenResources
|
||||
_nextPageItem.IsEnabled = currentPage < pageCount;
|
||||
_nextPageItem.PageNumber = Math.Min(pageCount, CurrentPage + 1);
|
||||
}
|
||||
|
||||
if (_quickJumper != null)
|
||||
{
|
||||
_quickJumper.Maximum = PageCount;
|
||||
}
|
||||
base.NotifyPageConditionChanged(currentPage, pageCount, pageSize, total);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == PageCountProperty)
|
||||
{
|
||||
if (_quickJumper != null)
|
||||
{
|
||||
_quickJumper.Maximum = PageCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleNavItemClicked(object? sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is PaginationNavItem navItemSender)
|
||||
@@ -111,7 +126,7 @@ public class SimplePagination : AbstractPagination, IControlSharedTokenResources
|
||||
|
||||
private void HandleLineEditKeyUp(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (sender is LineEdit lineEdit)
|
||||
if (sender is QuickJumpEdit lineEdit)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
@@ -120,10 +135,6 @@ public class SimplePagination : AbstractPagination, IControlSharedTokenResources
|
||||
var pageCount = (int)Math.Ceiling(Total / (double)PageSize);
|
||||
CurrentPage = Math.Max(1, Math.Min(pageNumber, pageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
lineEdit.Text = $"{CurrentPage}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,10 @@
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:PaginationTokenKey.ItemActiveBgDisabled}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ atom|IconPresenter#IconPresenter">
|
||||
<Setter Property="IconBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
|
||||
</Style>
|
||||
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<ControlTemplate>
|
||||
<StackPanel Name="{x:Static atom:PaginationThemeConstants.RootLayoutPart}"
|
||||
Orientation="Horizontal"
|
||||
IsVisible="{TemplateBinding IsEffectiveHideOnSinglePageVisible}">
|
||||
IsVisible="{TemplateBinding IsEffectiveVisible}">
|
||||
<ContentPresenter Name="{x:Static atom:PaginationThemeConstants.TotalInfoPresenterPart}"
|
||||
IsVisible="{TemplateBinding IsShowTotalInfo}"
|
||||
Content="{TemplateBinding TotalInfoText, Mode=Default, Converter={StaticResource StringToTextBlockConverter}}" />
|
||||
|
||||
@@ -9,18 +9,20 @@
|
||||
<ControlTemplate>
|
||||
<StackPanel Name="{x:Static atom:SimplePaginationThemeConstants.RootLayoutPart}"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
Orientation="Horizontal"
|
||||
IsVisible="{TemplateBinding IsEffectiveVisible}">
|
||||
<atom:PaginationNavItem Name="{x:Static atom:SimplePaginationThemeConstants.PreviousNavItemPart}"
|
||||
PaginationItemType="Previous"
|
||||
Icon="{antdicons:AntDesignIconProvider LeftOutlined}"
|
||||
SizeType="{TemplateBinding SizeType}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"/>
|
||||
<atom:LineEdit Name="{x:Static atom:SimplePaginationThemeConstants.QuickJumperPart}"
|
||||
IsVisible="{TemplateBinding IsReadOnly, Mode=Default, Converter={x:Static BoolConverters.Not}}"
|
||||
SizeType="{TemplateBinding SizeType}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"/>
|
||||
<atom:QuickJumpEdit Name="{x:Static atom:SimplePaginationThemeConstants.QuickJumperPart}"
|
||||
IsVisible="{TemplateBinding IsReadOnly, Mode=Default, Converter={x:Static BoolConverters.Not}}"
|
||||
SizeType="{TemplateBinding SizeType}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"
|
||||
Minimum="1"/>
|
||||
<atom:TextBlock Name="{x:Static atom:SimplePaginationThemeConstants.InfoIndicatorPart}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
|
||||
@@ -29,20 +29,11 @@
|
||||
VerticalAlignment="Center"
|
||||
Icon="{antdicons:AntDesignIconProvider DeleteOutlined}"
|
||||
IsVisible="{TemplateBinding IsCheckable, Converter={x:Static BoolConverters.Not}}"/>
|
||||
<Panel>
|
||||
<ContentPresenter Name="ContentPresenter"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
IsVisible="{TemplateBinding IsFiltering, Converter={x:Static BoolConverters.Not}}" />
|
||||
<atom:HighlightableTextBlock
|
||||
HighlightForeground="{TemplateBinding FilterHighlightForeground}"
|
||||
HighlightStrategy="{TemplateBinding FilterHighlightStrategy}"
|
||||
IsVisible="{TemplateBinding IsFiltering}"
|
||||
HighlightWords="{TemplateBinding FilterHighlightWords}"
|
||||
Text="{TemplateBinding ContentText}" />
|
||||
</Panel>
|
||||
<ContentPresenter Name="ContentPresenter"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
||||
@@ -5,54 +5,20 @@
|
||||
x:ClassModifier="internal">
|
||||
<ControlTheme x:Key="{x:Type atom:TransferListView}" TargetType="atom:TransferListView">
|
||||
<ControlTheme.BasedOn>
|
||||
<atom:ListBoxTheme TargetType="atom:TransferListView" />
|
||||
<atom:ListViewTheme TargetType="atom:TransferListView" />
|
||||
</ControlTheme.BasedOn>
|
||||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="atom:TransferListView">
|
||||
<Border Name="Frame"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding EffectiveBorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Margin="{TemplateBinding Margin}">
|
||||
<DockPanel LastChildFill="True">
|
||||
<atom:SimplePagination DockPanel.Dock="Bottom"
|
||||
Name="Pagination"
|
||||
Align="Start"
|
||||
IsHideOnSinglePage="True"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
SizeType="Small"
|
||||
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"/>
|
||||
<Panel>
|
||||
<atom:ScrollViewer Name="{x:Static atom:ListViewThemeConstants.ScrollViewerPart}"
|
||||
IsLiteMode="{TemplateBinding atom:ScrollViewer.IsLiteMode}"
|
||||
IsVisible="{TemplateBinding IsEffectiveEmptyVisible, Converter={x:Static BoolConverters.Not}}"
|
||||
AllowAutoHide="{TemplateBinding atom:ScrollViewer.AllowAutoHide}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||
IsScrollChainingEnabled="{TemplateBinding ScrollViewer.IsScrollChainingEnabled}"
|
||||
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
|
||||
IsScrollInertiaEnabled="{TemplateBinding ScrollViewer.IsScrollInertiaEnabled}">
|
||||
<ItemsPresenter Name="ItemsPresenter"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</atom:ScrollViewer>
|
||||
<ContentPresenter
|
||||
Name="EmptyIndicator"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Padding="{TemplateBinding EmptyIndicatorPadding}"
|
||||
IsVisible="{TemplateBinding IsEffectiveEmptyVisible}"
|
||||
Content="{TemplateBinding EmptyIndicator}"
|
||||
ContentTemplate="{TemplateBinding EmptyIndicatorTemplate}" />
|
||||
</Panel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
|
||||
<Setter Property="PaginationVisibility" Value="Bottom" />
|
||||
<Setter Property="BottomPaginationAlign" Value="Start" />
|
||||
<Setter Property="IsHideOnSinglePage" Value="False" />
|
||||
<Style Selector="^ /template/ ContentPresenter#TopPaginationPresenter">
|
||||
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:TransferTokenKey.PaginationMargin}}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ ContentPresenter#BottomPaginationPresenter">
|
||||
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:TransferTokenKey.PaginationMargin}}"/>
|
||||
</Style>
|
||||
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -549,7 +549,8 @@ public class Transfer : TemplatedControl,
|
||||
.Where(item => !(TargetKeys?.Contains(item.ItemKey ?? default) ?? false))
|
||||
.Where(item => !IsFilterEnabled || string.IsNullOrEmpty(SourceFilterValue) ||
|
||||
(Filter?.Filter(FilterValueSelector != null ? FilterValueSelector(item) : item,
|
||||
SourceFilterValue) ?? false));
|
||||
SourceFilterValue) ?? false))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
if (changeType.HasFlag(FilterChangeType.Target))
|
||||
@@ -557,7 +558,8 @@ public class Transfer : TemplatedControl,
|
||||
TargetPanelSource = ItemsSource?
|
||||
.Where(item => TargetKeys?.Contains(item.ItemKey ?? default) ?? false)
|
||||
.Where(item => !IsFilterEnabled || string.IsNullOrEmpty(TargetFilterValue) ||
|
||||
(Filter?.Filter(FilterValueSelector != null ? FilterValueSelector(item) : item, TargetFilterValue) ?? false));
|
||||
(Filter?.Filter(FilterValueSelector != null ? FilterValueSelector(item) : item, TargetFilterValue) ?? false))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ using Avalonia;
|
||||
|
||||
namespace AtomUI.Desktop.Controls;
|
||||
|
||||
public class TransferListItem : ListBoxItem
|
||||
public class TransferListItem : ListViewItem
|
||||
{
|
||||
#region 内部属性定义
|
||||
internal static readonly DirectProperty<TransferListItem, bool> IsCheckableProperty =
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Controls;
|
||||
using AtomUI.Controls.Data;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Desktop.Controls.Primitives;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
@@ -15,10 +12,9 @@ using VirtualizingStackPanel = Avalonia.Controls.VirtualizingStackPanel;
|
||||
|
||||
namespace AtomUI.Desktop.Controls;
|
||||
|
||||
public class TransferListView : ListBox, ITransferView
|
||||
public class TransferListView : ListView, ITransferView
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly DirectProperty<TransferListView, IList<EntityKey>?> SelectedKeysProperty =
|
||||
AvaloniaProperty.RegisterDirect<TransferListView, IList<EntityKey>?>(nameof(SelectedKeys),
|
||||
o => o.SelectedKeys,
|
||||
@@ -31,9 +27,6 @@ public class TransferListView : ListBox, ITransferView
|
||||
|
||||
public static readonly StyledProperty<bool> IsPaginationEnabledProperty =
|
||||
Transfer.IsPaginationEnabledProperty.AddOwner<TransferListView>();
|
||||
|
||||
public static readonly StyledProperty<int> PageSizeProperty =
|
||||
Transfer.PageSizeProperty.AddOwner<TransferListView>();
|
||||
|
||||
private IList<EntityKey>? _selectedKeys;
|
||||
public IList<EntityKey>? SelectedKeys
|
||||
@@ -54,12 +47,6 @@ public class TransferListView : ListBox, ITransferView
|
||||
get => GetValue(IsPaginationEnabledProperty);
|
||||
set => SetValue(IsPaginationEnabledProperty, value);
|
||||
}
|
||||
|
||||
public int PageSize
|
||||
{
|
||||
get => GetValue(PageSizeProperty);
|
||||
set => SetValue(PageSizeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsSupportItemTemplate => true;
|
||||
public bool IsSupportPagination => true;
|
||||
@@ -75,8 +62,6 @@ public class TransferListView : ListBox, ITransferView
|
||||
private bool _ignoreSyncSelection;
|
||||
private IList<EntityKey>? _selectedKeysBackup;
|
||||
private int _currentPageSizeBackup;
|
||||
private IListCollectionView? _listCollectionView;
|
||||
private SimplePagination? _pagination;
|
||||
|
||||
private static readonly FuncTemplate<Panel?> DefaultPanel =
|
||||
new(() => new VirtualizingStackPanel());
|
||||
@@ -102,10 +87,9 @@ public class TransferListView : ListBox, ITransferView
|
||||
return NeedsContainer<TransferListItem>(item, out recycleKey);
|
||||
}
|
||||
|
||||
protected override void PrepareListBoxItem(ListBoxItem listItem, object? item, int index,
|
||||
CompositeDisposable disposables)
|
||||
protected override void PrepareListViewItem(ListViewItem listItem, object? item, int index, CompositeDisposable disposables)
|
||||
{
|
||||
base.PrepareListBoxItem(listItem, item, index, disposables);
|
||||
base.PrepareListViewItem(listItem, item, index, disposables);
|
||||
if (listItem is TransferListItem transferListItem)
|
||||
{
|
||||
disposables.Add(BindUtils.RelayBind(this, IsSelectableProperty, transferListItem, TransferListItem.IsCheckableProperty));
|
||||
@@ -133,15 +117,6 @@ public class TransferListView : ListBox, ITransferView
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == ItemsSourceProperty)
|
||||
{
|
||||
Selection.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSelectedKeysChanged()
|
||||
{
|
||||
SelectedKeyChanged?.Invoke(this, EventArgs.Empty);
|
||||
@@ -154,10 +129,7 @@ public class TransferListView : ListBox, ITransferView
|
||||
SetCurrentValue(SelectedItemsProperty, selectedItems);
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
Selection.Clear();
|
||||
}
|
||||
public void DeselectAll() => Selection.Clear();
|
||||
|
||||
void ITransferView.SetPaginationEnabled(bool enabled)
|
||||
{
|
||||
@@ -166,104 +138,19 @@ public class TransferListView : ListBox, ITransferView
|
||||
|
||||
void ITransferView.SetItemsSource(IEnumerable? itemsSource)
|
||||
{
|
||||
if (!IsPaginationEnabled)
|
||||
{
|
||||
SetCurrentValue(ItemsSourceProperty, itemsSource);
|
||||
_listCollectionView = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldCollectionView = _listCollectionView;
|
||||
var newItemsSource = itemsSource;
|
||||
|
||||
_listCollectionView = null;
|
||||
IListCollectionView? newCollectionView;
|
||||
if (newItemsSource is IListCollectionView)
|
||||
{
|
||||
newCollectionView = (IListCollectionView)newItemsSource;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCollectionView = newItemsSource is not null
|
||||
? CreateView(newItemsSource)
|
||||
: default;
|
||||
}
|
||||
if (oldCollectionView != null)
|
||||
{
|
||||
if (oldCollectionView is ListCollectionView oldDataGridCollectionView)
|
||||
{
|
||||
oldDataGridCollectionView.PageChanging -= HandlePageChanging;
|
||||
}
|
||||
}
|
||||
if (newCollectionView != null)
|
||||
{
|
||||
if (newCollectionView is ListCollectionView newDataGridCollectionView)
|
||||
{
|
||||
newDataGridCollectionView.PageChanging += HandlePageChanging;
|
||||
}
|
||||
}
|
||||
|
||||
_listCollectionView = newCollectionView;
|
||||
|
||||
if (oldCollectionView != newCollectionView)
|
||||
{
|
||||
SetCurrentValue(ItemsSourceProperty, _listCollectionView);
|
||||
}
|
||||
ReConfigurePagination();
|
||||
}
|
||||
}
|
||||
|
||||
internal static IListCollectionView CreateView(IEnumerable source)
|
||||
{
|
||||
Debug.Assert(source != null, "source unexpectedly null");
|
||||
Debug.Assert(!(source is IListCollectionView), "source is an IListCollectionView");
|
||||
|
||||
IListCollectionView? collectionView = null;
|
||||
|
||||
if (source is IListCollectionViewFactory collectionViewFactory)
|
||||
{
|
||||
// If the source is a collection view factory, give it a chance to produce a custom collection view.
|
||||
collectionView = collectionViewFactory.CreateView();
|
||||
// Intentionally not catching potential exception thrown by ICollectionViewFactory.CreateView().
|
||||
}
|
||||
if (collectionView == null)
|
||||
{
|
||||
// If we still do not have a collection view, default to a PagedCollectionView.
|
||||
collectionView = new ListCollectionView(source);
|
||||
}
|
||||
return collectionView;
|
||||
}
|
||||
|
||||
private void HandlePageChanging(object? sender, PageChangingEventArgs args)
|
||||
{
|
||||
var targetPage = args.NewPageIndex + 1;
|
||||
if (_pagination != null && _pagination.CurrentPage != targetPage)
|
||||
{
|
||||
_pagination.CurrentPage = targetPage;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReConfigurePagination()
|
||||
{
|
||||
if (IsSupportPagination && IsPaginationEnabled)
|
||||
{
|
||||
if (_listCollectionView is ListCollectionView collectionView)
|
||||
{
|
||||
collectionView.PageSize = PageSize;
|
||||
if (_pagination != null)
|
||||
{
|
||||
_pagination.Total = collectionView.ItemCount;
|
||||
_pagination.PageSize = PageSize;
|
||||
_pagination.CurrentPage = Pagination.DefaultCurrentPage;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetCurrentValue(ItemsSourceProperty, itemsSource);
|
||||
}
|
||||
|
||||
void ITransferView.NotifyAboutToTransfer(TransferDirection transferDirection)
|
||||
{
|
||||
_selectedKeysBackup = SelectedKeys;
|
||||
_currentPageSizeBackup = _pagination?.CurrentPage ?? 1;
|
||||
_selectedKeysBackup = SelectedKeys;
|
||||
if (IsPaginationEnabled && BottomPagination != null)
|
||||
{
|
||||
if (ItemsSource is IListCollectionView listCollectionView)
|
||||
{
|
||||
_currentPageSizeBackup = listCollectionView.PageIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ITransferView.NotifyTransferCompleted(TransferDirection transferDirection)
|
||||
@@ -280,15 +167,19 @@ public class TransferListView : ListBox, ITransferView
|
||||
{
|
||||
SetCurrentValue(SelectedKeysProperty, null);
|
||||
}
|
||||
|
||||
if (IsPaginationEnabled && _pagination != null)
|
||||
|
||||
if (IsPaginationEnabled && BottomPagination != null)
|
||||
{
|
||||
var pageCount = _pagination.PageCount;
|
||||
var newPageCount = _currentPageSizeBackup <= pageCount ? _currentPageSizeBackup : pageCount;
|
||||
_pagination.CurrentPage = newPageCount;
|
||||
if (ItemsSource is IListCollectionView listCollectionView)
|
||||
{
|
||||
var pageCount = listCollectionView.TotalItemCount / listCollectionView.PageSize;
|
||||
var newPageCount = _currentPageSizeBackup <= pageCount ? _currentPageSizeBackup : pageCount;
|
||||
listCollectionView.MoveToPage(newPageCount);
|
||||
}
|
||||
}
|
||||
|
||||
_selectedKeysBackup = null;
|
||||
_currentPageSizeBackup = 1;
|
||||
_currentPageSizeBackup = 0;
|
||||
}
|
||||
|
||||
void ITransferView.SetSelectionEnabled(bool enabled)
|
||||
@@ -320,39 +211,19 @@ public class TransferListView : ListBox, ITransferView
|
||||
{
|
||||
if (e.Source is CheckBox checkBox && GetContainerFromEventSource(e.Source) is TransferListItem listItem)
|
||||
{
|
||||
listItem.SetCurrentValue(IsSelectedProperty, checkBox.IsChecked == true);
|
||||
UpdateSelection(listItem, checkBox.IsChecked == true, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectAll() => Selection.SelectAll();
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_pagination = e.NameScope.Find<SimplePagination>("Pagination");
|
||||
if (_pagination != null)
|
||||
SetCurrentValue(BottomPaginationProperty, new SimplePagination()
|
||||
{
|
||||
_pagination.CurrentPageChanged += HandlePageChangeRequest;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePageChangeRequest(object? sender, PageChangedEventArgs args)
|
||||
{
|
||||
if (_listCollectionView is ListCollectionView collectionView)
|
||||
{
|
||||
collectionView.MoveToPage(args.PageIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||
{
|
||||
var selection = this.GetSelection();
|
||||
if (selection == null)
|
||||
{
|
||||
selection = new TransferListViewSelectionModel
|
||||
{
|
||||
SingleSelect = !SelectionMode.HasAllFlags(SelectionMode.Multiple),
|
||||
};
|
||||
this.InitializeSelectionModel(selection);
|
||||
}
|
||||
base.PrepareContainerForItemOverride(container, item, index);
|
||||
IsReadOnly = false,
|
||||
SizeType = SizeType.Small
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,11 @@ internal class TransferToken : AbstractControlDesignToken
|
||||
/// </summary>
|
||||
public Thickness HeaderPadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分页器的外边距
|
||||
/// </summary>
|
||||
public Thickness PaginationMargin { get; set; }
|
||||
|
||||
public override void CalculateTokenValues(bool isDarkMode)
|
||||
{
|
||||
base.CalculateTokenValues(isDarkMode);
|
||||
@@ -65,5 +70,6 @@ internal class TransferToken : AbstractControlDesignToken
|
||||
ItemPadding = new Thickness(0, (SharedToken.ControlHeight - SharedToken.FontHeight) / 2);
|
||||
HeaderPadding = new Thickness(SharedToken.UniformlyPaddingSM,
|
||||
Math.Ceiling((SharedToken.ControlHeightLG - SharedToken.LineWidth - SharedToken.FontHeight) / 2));
|
||||
PaginationMargin = new Thickness(0, SharedToken.UniformlyMarginXXS);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user