Dispenser/DispenserUI/Views/Controls/Table.axaml.cs

253 lines
7.2 KiB
C#
Raw Permalink Normal View History

2024-08-16 07:20:09 +00:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using DynamicData;
using DispenserCommon.Atrributes;
using DispenserCommon.Utils;
using Masuit.Tools;
namespace DispenserUI.Views.Controls;
public partial class Table : UserControl
{
public static readonly StyledProperty<IEnumerable> ItemsProperty =
AvaloniaProperty.Register<Table, IEnumerable>(nameof(Items));
public static readonly StyledProperty<int> TotalProperty =
AvaloniaProperty.Register<Table, int>(nameof(Total));
public static readonly StyledProperty<int> PageSizeProperty =
AvaloniaProperty.Register<Table, int>(nameof(PageSize));
public static readonly StyledProperty<int> CurrentPageProperty =
AvaloniaProperty.Register<Table, int>(nameof(CurrentPage));
public static readonly StyledProperty<int> PagesProperty =
AvaloniaProperty.Register<Table, int>(nameof(Pages));
public static readonly StyledProperty<bool> ShowIndexProperty =
AvaloniaProperty.Register<Table, bool>(nameof(ShowIndex), true);
public static readonly StyledProperty<int> MaxDisplayPagesProperty =
AvaloniaProperty.Register<Table, int>(nameof(MaxDisplayPages), 10);
public event EventHandler<int> NextPage;
public event EventHandler<int> PreviousPage;
public event EventHandler<int> PageChanged;
public Table()
{
InitializeComponent();
TableContent = this.FindControl<DataGrid>("TableContent");
PrePageBtn = this.FindControl<Button>("PrePageBtn");
NextPageBtn = this.FindControl<Button>("NextPageBtn");
PageRepeater = this.FindControl<StackPanel>("PageRepeater");
this.GetObservable(ItemsProperty).Subscribe(its =>
{
Items = its;
Dispatcher.UIThread.InvokeAsync(RenderTable);
});
PrePageBtn!.Click += OnPreviousPage;
NextPageBtn!.Click += OnNextPage;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public IEnumerable Items
{
get => GetValue(ItemsProperty);
set => SetValue(ItemsProperty, value);
}
public int Total
{
get => GetValue(TotalProperty);
set => SetValue(TotalProperty, value);
}
public int PageSize
{
get => GetValue(PageSizeProperty);
set => SetValue(PageSizeProperty, value);
}
public bool ShowIndex
{
get => GetValue(ShowIndexProperty);
set => SetValue(ShowIndexProperty, value);
}
public int CurrentPage
{
get => GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value);
}
public int Pages
{
get => GetValue(PagesProperty);
set => SetValue(PagesProperty, value);
}
public int MaxDisplayPages
{
get => GetValue(MaxDisplayPagesProperty);
set => SetValue(MaxDisplayPagesProperty, value);
}
/// <summary>
/// 上一页
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnPreviousPage(object? sender, RoutedEventArgs e)
{
if (CurrentPage == 1)
{
ToastUtil.Info("无上一页数据");
return;
}
PreviousPage?.Invoke(this, CurrentPage - 1);
}
/// <summary>
/// 下一页
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnNextPage(object? sender, RoutedEventArgs e)
{
if (CurrentPage == Pages)
{
ToastUtil.Info("无下一页数据");
return;
}
NextPage?.Invoke(this, CurrentPage + 1);
}
private void RenderTable()
{
TableContent.ItemsSource = new List<object>();
TableContent.Columns.Clear();
if (Items.IsNullOrEmpty()) return;
if (ShowIndex)
{
var index = new DataGridTextColumn
{
Header = "序号",
Width = new DataGridLength(80),
Binding = new Binding
{
RelativeSource = new RelativeSource
{
Mode = RelativeSourceMode.FindAncestor,
AncestorType = typeof(DataGridRow),
},
Path = "Header"
},
};
TableContent.Columns.Add(index);
TableContent.LoadingRow += LoadingRow;
}
TableContent.ItemsSource = Items;
List<DataGridTextColumn> columns = [];
foreach (var item in Items)
{
var type = item.GetType();
var properties =
type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (var property in properties)
{
var description = property.GetCustomAttribute<DescriptionAttribute>();
var hide = property.GetCustomAttribute<Hide>();
if (hide != null) continue;
var column = new DataGridTextColumn
{
Header = description!.Description,
Binding = new Binding(property.Name),
Width = new DataGridLength(1, DataGridLengthUnitType.Star)
};
columns.Add(column);
}
TableContent.Columns.AddRange(columns);
break;
}
// 计算显示的起始页和结束页
int startPage = Math.Max(1, CurrentPage - MaxDisplayPages / 2);
int endPage = Math.Min(Pages, startPage + MaxDisplayPages - 1);
// 如果起始页被推前了(例如,当前页靠近总页数末尾)
if (endPage - startPage + 1 < MaxDisplayPages)
{
startPage = Math.Max(1, endPage - MaxDisplayPages + 1);
}
// 渲染导航栏,最多只显示10页
List<Button> pageButtons = [];
for (var i = startPage; i <= endPage; i++)
{
var page = i;
var btn = new Button
{
Content = i,
Width = 30,
Height = 30,
Foreground = Brushes.Black,
FontSize = 12,
Background = Brushes.Transparent,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
Margin = new Thickness(5, 0, 5, 0)
};
if (i == CurrentPage)
{
btn.Foreground = Brushes.DodgerBlue;
btn.FontWeight = FontWeight.Bold;
}
btn.Click += (sender, args) =>
{
CurrentPage = page;
PageChanged?.Invoke(this, page);
};
pageButtons.Add(btn);
}
PageRepeater.Children.Clear();
PageRepeater.Children.AddRange(pageButtons);
}
private void LoadingRow(object? sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
}