antdui-demo/Views/SubView/InputTable.cs
zhubanghao e5dfc6f2bd
2025-03-28 15:33:20 +08:00

265 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AntdUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace AntdUIDemo
{
/// <summary>
/// InputTable泛型控件
/// </summary>
/// <typeparam name="T"></typeparam>
public partial class InputTable<T> : UserControl where T : class
{
#region
private Table _table;
private Form _popover;
private T _selectedItem;
#endregion
#region
/// <summary>
/// 数据源集合
/// </summary>
[Category("Data")]
[Description("数据源集合")]
public List<T> DataSource { get; set; } = new List<T>();
/// <summary>
/// 列配置集合
/// </summary>
[Category("Data")]
[Description("列配置集合")]
public ColumnCollection Columns { get; set; } = new ColumnCollection();
/// <summary>
/// 搜索框占位符文本
/// </summary>
[Category("Behavior")]
[Description("搜索框占位符文本")]
public string PlaceholderText
{
get => txtSearch.PlaceholderText;
set => txtSearch.PlaceholderText = value;
}
/// <summary>
/// 当前选中的对象
/// </summary>
[Browsable(false)]
public T SelectedItem
{
get => _selectedItem;
private set
{
if (EqualityComparer<T>.Default.Equals(_selectedItem, value)) return;
_selectedItem = value;
SelectedItemChanged?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// 显示文本格式化委托
/// </summary>
[Category("Behavior")]
[Description("显示文本格式化委托")]
public Func<T, string> DisplayTextFormatter { get; set; }
#endregion
#region
/// <summary>
///
/// </summary>
public event EventHandler SelectedItemChanged;
/// <summary>
///
/// </summary>
public event EventHandler SearchButtonClick;
#endregion
#region
public InputTable()
{
InitializeComponent();
txtSearch.TextChanged += TxtSearch_TextChanged;
btnSearch.Click += BtnSearch_Click;
InitializeTable();
}
#endregion
#region
private void InitializeTable()
{
if (DesignMode) return;
_table = new Table
{
Columns = Columns,
Size = new Size(txtSearch.Width, 300),
Font = "Microsoft YaHei UI, 9pt",
};
_table.CellDoubleClick += Table_CellDoubleClick;
}
#endregion
#region
/// <summary>
/// 更新Table数据源
/// </summary>
private void UpdateTableDataSource()
{
if (_table == null || _table.IsDisposed) return;
var filtered = (List<T>)ApplySearchFilter(DataSource).ToList();
_table.DataSource = filtered;
}
private IEnumerable<T> ApplySearchFilter(IEnumerable<T> source)
{
if (string.IsNullOrWhiteSpace(txtSearch.Text))
return source;
return source.Where(item => Columns.Any(col =>
{
var propValue = GetPropertyValue(item, col.Key);
return propValue.ToString().Contains(txtSearch.Text) ;
})
);
}
private object GetPropertyValue(T item, string propertyName)
{
return item.GetType()
.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase)?
.GetValue(item);
}
#endregion
#region
private void TxtSearch_TextChanged(object sender, EventArgs e)
{
if (_popover == null)
{
if (_table == null || _table.IsDisposed) InitializeTable();
UpdateTableDataSource();
ShowPopover();
}
else
{
UpdateTableDataSource();
}
}
/// <summary>
/// 获取当前对象
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnSearch_Click(object sender, EventArgs e)
{
SearchButtonClick?.Invoke(this, e);
}
/// <summary>
/// Table双击
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Table_CellDoubleClick(object sender, TableClickEventArgs e)
{
if (e.Record is T selected)
{
SelectedItem = selected;
UpdateSearchText(selected);
ClosePopover();
}
}
/// <summary>
/// 释放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Popover_Disposed(object sender, EventArgs e)
{
_popover = null;
}
#endregion
#region UI控制方法
private void ShowPopover()
{
if (_table == null) return;
// 动态获取实际宽度
var controlWidth = txtSearch.Width > 10 ? txtSearch.Width : 200; // 设置默认最小值
_table.Size = new Size(controlWidth, 300);
_popover = Popover.open(new Popover.Config(txtSearch, _table)
{
OnControlLoad = () => BeginInvoke(new Action(() =>
{
txtSearch.Focus();
txtSearch.SelectAll();
}))
});
_popover.Disposed += Popover_Disposed;
}
protected override void OnLayout(LayoutEventArgs e)
{
base.OnLayout(e);
// 布局变化时同步表格尺寸
if (_table != null && !_table.IsDisposed)
{
_table.Width = txtSearch.Width;
}
}
private void ClosePopover()
{
_popover?.Close();
_popover = null;
}
private void UpdateSearchText(T item)
{
txtSearch.Text = DisplayTextFormatter?.Invoke(item) ?? item.ToString();
}
#endregion
#region
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
_table?.Dispose();
ClosePopover();
}
base.Dispose(disposing);
}
#endregion
}
}