Feature(Pagination): add QuickJumpEdit control

This commit is contained in:
chinboy
2026-03-18 23:41:52 +08:00
parent 21d45de71b
commit b36a6ed76e
17 changed files with 177 additions and 256 deletions
@@ -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"/>
@@ -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);
}
}