inputTable组合控件

This commit is contained in:
zhubanghao 2025-03-28 15:22:57 +08:00
parent 0dcfd51c33
commit 6bdbdd813b
4 changed files with 437 additions and 2 deletions

View File

@ -80,6 +80,8 @@
this.input1 = new AntdUI.Input(); this.input1 = new AntdUI.Input();
this.label3 = new AntdUI.Label(); this.label3 = new AntdUI.Label();
this.tooltipComponent1 = new AntdUI.TooltipComponent(); this.tooltipComponent1 = new AntdUI.TooltipComponent();
this.label1 = new AntdUI.Label();
this.panel2 = new AntdUI.Panel();
this.stackPanel1.SuspendLayout(); this.stackPanel1.SuspendLayout();
this.flowPanel10.SuspendLayout(); this.flowPanel10.SuspendLayout();
this.flowPanel9.SuspendLayout(); this.flowPanel9.SuspendLayout();
@ -112,6 +114,8 @@
// stackPanel1 // stackPanel1
// //
this.stackPanel1.AutoScroll = true; this.stackPanel1.AutoScroll = true;
this.stackPanel1.Controls.Add(this.panel2);
this.stackPanel1.Controls.Add(this.label1);
this.stackPanel1.Controls.Add(this.flowPanel10); this.stackPanel1.Controls.Add(this.flowPanel10);
this.stackPanel1.Controls.Add(this.label12); this.stackPanel1.Controls.Add(this.label12);
this.stackPanel1.Controls.Add(this.flowPanel9); this.stackPanel1.Controls.Add(this.flowPanel9);
@ -135,7 +139,7 @@
this.stackPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.stackPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.stackPanel1.Location = new System.Drawing.Point(0, 74); this.stackPanel1.Location = new System.Drawing.Point(0, 74);
this.stackPanel1.Name = "stackPanel1"; this.stackPanel1.Name = "stackPanel1";
this.stackPanel1.Size = new System.Drawing.Size(750, 797); this.stackPanel1.Size = new System.Drawing.Size(750, 936);
this.stackPanel1.TabIndex = 0; this.stackPanel1.TabIndex = 0;
this.stackPanel1.Text = "stackPanel1"; this.stackPanel1.Text = "stackPanel1";
this.stackPanel1.Vertical = true; this.stackPanel1.Vertical = true;
@ -660,12 +664,29 @@
this.tooltipComponent1.ArrowAlign = AntdUI.TAlign.TL; this.tooltipComponent1.ArrowAlign = AntdUI.TAlign.TL;
this.tooltipComponent1.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.tooltipComponent1.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
// //
// label1
//
this.label1.Font = new System.Drawing.Font("Microsoft YaHei UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.label1.Location = new System.Drawing.Point(3, 781);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(744, 24);
this.label1.TabIndex = 31;
this.label1.Text = "Input+Popover+Table组合控件";
//
// panel2
//
this.panel2.Location = new System.Drawing.Point(3, 811);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(744, 82);
this.panel2.TabIndex = 32;
this.panel2.Text = "panel2";
//
// InputDemo // InputDemo
// //
this.Controls.Add(this.stackPanel1); this.Controls.Add(this.stackPanel1);
this.Controls.Add(this.header1); this.Controls.Add(this.header1);
this.Name = "InputDemo"; this.Name = "InputDemo";
this.Size = new System.Drawing.Size(750, 871); this.Size = new System.Drawing.Size(750, 1010);
this.stackPanel1.ResumeLayout(false); this.stackPanel1.ResumeLayout(false);
this.flowPanel10.ResumeLayout(false); this.flowPanel10.ResumeLayout(false);
this.flowPanel9.ResumeLayout(false); this.flowPanel9.ResumeLayout(false);
@ -736,5 +757,7 @@
private AntdUI.Input input19; private AntdUI.Input input19;
private AntdUI.Input input22; private AntdUI.Input input22;
private AntdUI.Input input23; private AntdUI.Input input23;
private AntdUI.Label label1;
private AntdUI.Panel panel2;
} }
} }

View File

@ -1,5 +1,7 @@
using AntdUI; using AntdUI;
using System; using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -13,6 +15,7 @@ namespace AntdUIDemo.Views
InitializeComponent(); InitializeComponent();
// 绑定事件 // 绑定事件
BindEventHandler(); BindEventHandler();
InitInputTable();
} }
private void BindEventHandler() private void BindEventHandler()
@ -61,5 +64,73 @@ namespace AntdUIDemo.Views
} }
return true; return true;
} }
#region Input+Popover+Table
Form form;
/// <summary>
/// 小蚂蚁QQ:897252348
/// </summary>
private void InitInputTable()
{
var customerInput = new InputTable<Customer>
{
Dock = DockStyle.Fill,
Columns =
{
new Column("Code", "客户编号"),
new Column("Name", "客户名称"),
new Column("Address", "联系地址")
},
DisplayTextFormatter = c => $"{c.Code} - {c.Name}",
DataSource = GetCustomers()
};
customerInput.SelectedItemChanged += (s, e) =>
{
if (customerInput.SelectedItem != null)
{
AntdUI.Message.info(form, $"选中客户:{customerInput.SelectedItem.Code}", autoClose: 3);
}
};
customerInput.SearchButtonClick += (s, e) =>
{
if (customerInput.SelectedItem != null)
{
AntdUI.Message.success(form, $"选中客户:{customerInput.SelectedItem.Code}", autoClose: 3);
}
};
customerInput.Size = new Size(300, 50);
customerInput.Location = new Point(label1.Location.X, label1.Location.Y+20);
panel2.Controls.Add(customerInput);
}
//集合
List<Customer> GetCustomers()
{
var customers = new List<Customer>();
for (int i = 0; i < 100; i++)
{
customers.Add(new Customer
{
Address = $"地址{i}",
Code = i.ToString(),
Name = $"名字{i}",
});
}
return customers;
}
// 定义实体类
public class Customer
{
public string Code { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
#endregion
} }
} }

79
Views/SubView/InputTable.Designer.cs generated Normal file
View File

@ -0,0 +1,79 @@
using System.Drawing;
using System.Windows.Forms;
namespace AntdUIDemo
{
partial class InputTable<T>
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
#region
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
InputSearch = new AntdUI.Panel();
txtSearch = new AntdUI.Input();
btnSearch = new AntdUI.Button();
InputSearch.SuspendLayout();
SuspendLayout();
//
// InputSearch
//
InputSearch.Controls.Add(txtSearch);
InputSearch.Controls.Add(btnSearch);
InputSearch.Dock = DockStyle.Fill;
InputSearch.Location = new Point(0, 0);
InputSearch.Name = "InputSearch";
InputSearch.Size = new Size(297, 52);
InputSearch.TabIndex = 3;
InputSearch.Text = "panel1";
//
// txtSearch
//
txtSearch.Dock = DockStyle.Fill;
txtSearch.IconRatio = 1F;
txtSearch.Location = new Point(0, 0);
txtSearch.Name = "txtSearch";
txtSearch.PlaceholderText = "输入点什么搜索";
txtSearch.Size = new Size(251, 52);
txtSearch.SuffixSvg = "";
txtSearch.TabIndex = 0;
//
// btnSearch
//
btnSearch.Dock = DockStyle.Right;
btnSearch.IconRatio = 1F;
btnSearch.IconSvg = "SearchOutlined";
btnSearch.Location = new Point(251, 0);
btnSearch.Name = "btnSearch";
btnSearch.Size = new Size(46, 52);
btnSearch.TabIndex = 1;
btnSearch.Type = AntdUI.TTypeMini.Info;
//
// InputTable
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
Controls.Add(InputSearch);
Name = "InputTable";
Size = new Size(297, 52);
InputSearch.ResumeLayout(false);
ResumeLayout(false);
}
#endregion
private AntdUI.Panel InputSearch;
private AntdUI.Input txtSearch;
private AntdUI.Button btnSearch;
}
}

262
Views/SubView/InputTable.cs Normal file
View File

@ -0,0 +1,262 @@
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)
};
_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
}
}